chef-zero 2.2.1 → 3.0.0.rc.1
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/README.md +2 -0
- data/Rakefile +5 -1
- data/bin/chef-zero +17 -0
- data/lib/chef_zero/chef_data/acl_path.rb +139 -0
- data/lib/chef_zero/chef_data/cookbook_data.rb +240 -0
- data/lib/chef_zero/chef_data/data_normalizer.rb +207 -0
- data/lib/chef_zero/chef_data/default_creator.rb +446 -0
- data/lib/chef_zero/data_store/default_facade.rb +149 -0
- data/lib/chef_zero/data_store/interface_v1.rb +18 -0
- data/lib/chef_zero/data_store/memory_store.rb +2 -1
- data/lib/chef_zero/data_store/memory_store_v2.rb +3 -36
- data/lib/chef_zero/data_store/raw_file_store.rb +147 -0
- data/lib/chef_zero/data_store/v1_to_v2_adapter.rb +39 -103
- data/lib/chef_zero/data_store/v2_to_v1_adapter.rb +1 -1
- data/lib/chef_zero/endpoints/acl_endpoint.rb +38 -0
- data/lib/chef_zero/endpoints/acls_endpoint.rb +29 -0
- data/lib/chef_zero/endpoints/actor_endpoint.rb +36 -10
- data/lib/chef_zero/endpoints/actors_endpoint.rb +38 -6
- data/lib/chef_zero/endpoints/authenticate_user_endpoint.rb +15 -9
- data/lib/chef_zero/endpoints/container_endpoint.rb +22 -0
- data/lib/chef_zero/endpoints/containers_endpoint.rb +13 -0
- data/lib/chef_zero/endpoints/cookbook_endpoint.rb +1 -1
- data/lib/chef_zero/endpoints/cookbook_version_endpoint.rb +15 -14
- data/lib/chef_zero/endpoints/cookbooks_base.rb +2 -2
- data/lib/chef_zero/endpoints/data_bag_endpoint.rb +4 -4
- data/lib/chef_zero/endpoints/data_bag_item_endpoint.rb +5 -5
- data/lib/chef_zero/endpoints/data_bags_endpoint.rb +5 -4
- data/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb +2 -2
- data/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb +6 -6
- data/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb +2 -2
- data/lib/chef_zero/endpoints/environment_endpoint.rb +5 -5
- data/lib/chef_zero/endpoints/environment_nodes_endpoint.rb +2 -2
- data/lib/chef_zero/endpoints/environment_recipes_endpoint.rb +3 -3
- data/lib/chef_zero/endpoints/environment_role_endpoint.rb +2 -2
- data/lib/chef_zero/endpoints/file_store_file_endpoint.rb +1 -1
- data/lib/chef_zero/endpoints/group_endpoint.rb +20 -0
- data/lib/chef_zero/endpoints/groups_endpoint.rb +13 -0
- data/lib/chef_zero/endpoints/license_endpoint.rb +25 -0
- data/lib/chef_zero/endpoints/node_endpoint.rb +5 -5
- data/lib/chef_zero/endpoints/not_found_endpoint.rb +2 -2
- data/lib/chef_zero/endpoints/organization_association_request_endpoint.rb +22 -0
- data/lib/chef_zero/endpoints/organization_association_requests_endpoint.rb +29 -0
- data/lib/chef_zero/endpoints/organization_authenticate_user_endpoint.rb +26 -0
- data/lib/chef_zero/endpoints/organization_endpoint.rb +41 -0
- data/lib/chef_zero/endpoints/organization_user_endpoint.rb +48 -0
- data/lib/chef_zero/endpoints/organization_users_endpoint.rb +14 -0
- data/lib/chef_zero/endpoints/organization_validator_key_endpoint.rb +20 -0
- data/lib/chef_zero/endpoints/organizations_endpoint.rb +55 -0
- data/lib/chef_zero/endpoints/principal_endpoint.rb +15 -3
- data/lib/chef_zero/endpoints/rest_list_endpoint.rb +8 -6
- data/lib/chef_zero/endpoints/rest_object_endpoint.rb +12 -10
- data/lib/chef_zero/endpoints/role_endpoint.rb +5 -5
- data/lib/chef_zero/endpoints/role_environments_endpoint.rb +2 -2
- data/lib/chef_zero/endpoints/sandbox_endpoint.rb +2 -2
- data/lib/chef_zero/endpoints/sandboxes_endpoint.rb +4 -4
- data/lib/chef_zero/endpoints/search_endpoint.rb +10 -10
- data/lib/chef_zero/endpoints/system_recovery_endpoint.rb +30 -0
- data/lib/chef_zero/endpoints/user_association_request_endpoint.rb +40 -0
- data/lib/chef_zero/endpoints/user_association_requests_count_endpoint.rb +19 -0
- data/lib/chef_zero/endpoints/user_association_requests_endpoint.rb +19 -0
- data/lib/chef_zero/endpoints/user_organizations_endpoint.rb +22 -0
- data/lib/chef_zero/rest_base.rb +79 -13
- data/lib/chef_zero/rest_error_response.rb +1 -1
- data/lib/chef_zero/rest_request.rb +4 -0
- data/lib/chef_zero/rest_router.rb +1 -0
- data/lib/chef_zero/rspec.rb +55 -8
- data/lib/chef_zero/server.rb +87 -21
- data/lib/chef_zero/version.rb +1 -1
- data/spec/run_oc_pedant.rb +53 -0
- data/spec/{run.rb → run_pedant.rb} +13 -4
- data/spec/server_spec.rb +54 -0
- data/spec/support/oc_pedant.rb +134 -0
- data/spec/support/pedant.rb +1 -1
- metadata +54 -13
- data/lib/chef_zero/cookbook_data.rb +0 -236
- data/lib/chef_zero/data_normalizer.rb +0 -146
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c3b229916ca80eb41cf861bc986a0bbc8198b7f
|
4
|
+
data.tar.gz: b4579df1962991a5f8377528e8e296ac2b25a22c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96d614e76573211f42078149a7db53d41e455c211f9278166b8a2c4318dd68ef9d13eb00349a23fe980f54ee5dd5761fa12098ffdea89eee0cce1249d96f8ae9
|
7
|
+
data.tar.gz: e0ae0d2811a84bb800f2f46135f6279cb2eddef045491ed7764c42f137b208fc9d4b02bf10f8a9940e202aad81b87e7095435d49d8c37029d4659dbc502f5b9c
|
data/README.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
[](https://waffle.io/opscode/chef-zero)[](https://waffle.io/opscode/chef-zero)
|
2
|
+
|
1
3
|
Chef Zero
|
2
4
|
=========
|
3
5
|
|
data/Rakefile
CHANGED
data/bin/chef-zero
CHANGED
@@ -8,6 +8,7 @@ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
|
|
8
8
|
|
9
9
|
require 'chef_zero/version'
|
10
10
|
require 'chef_zero/server'
|
11
|
+
require 'chef_zero/data_store/raw_file_store'
|
11
12
|
require 'optparse'
|
12
13
|
|
13
14
|
def parse_port(port)
|
@@ -49,6 +50,18 @@ OptionParser.new do |opts|
|
|
49
50
|
options[:log_level] = value
|
50
51
|
end
|
51
52
|
|
53
|
+
opts.on("--multi-org", "Whether to run in multi-org mode") do |value|
|
54
|
+
options[:single_org] = nil
|
55
|
+
end
|
56
|
+
|
57
|
+
opts.on("--file-store PATH", "Persist data to files at the given path") do |value|
|
58
|
+
options[:data_store] = ChefZero::DataStore::RawFileStore.new(value)
|
59
|
+
end
|
60
|
+
|
61
|
+
opts.on("--[no-]ssl", "Use SSL with self-signed certificate(Auto generate before every run). Default: false.") do |value|
|
62
|
+
options[:ssl] = value
|
63
|
+
end
|
64
|
+
|
52
65
|
opts.on_tail("-h", "--help", "Show this message") do
|
53
66
|
puts opts
|
54
67
|
exit
|
@@ -60,6 +73,10 @@ OptionParser.new do |opts|
|
|
60
73
|
end
|
61
74
|
end.parse!
|
62
75
|
|
76
|
+
if options[:data_store]
|
77
|
+
options[:data_store] = ChefZero::DataStore::DefaultFacade.new(options[:data_store], options[:single_org], false)
|
78
|
+
end
|
79
|
+
|
63
80
|
server = ChefZero::Server.new(options)
|
64
81
|
|
65
82
|
if options[:daemon]
|
@@ -0,0 +1,139 @@
|
|
1
|
+
module ChefZero
|
2
|
+
module ChefData
|
3
|
+
# Manages translations between REST and ACL data paths
|
4
|
+
# and parent paths.
|
5
|
+
#
|
6
|
+
# Suggestions
|
7
|
+
# - make /organizations/ORG/_acl and deprecate organization/_acl and organizations/_acl
|
8
|
+
# - add endpoints for /containers/(users|organizations|containers)(/_acl)
|
9
|
+
# - add PUT for */_acl
|
10
|
+
# - add endpoints for /organizations/ORG/data/containers and /organizations/ORG/cookbooks/containers
|
11
|
+
# - sane, fully documented ACL model
|
12
|
+
# - sane inheritance / override model: if actors or groups are explicitly
|
13
|
+
# specified on X, they are not inherited from X's parent
|
14
|
+
# - stop adding pivotal to acls (he already has access to what he needs)
|
15
|
+
module AclPath
|
16
|
+
ORG_DATA_TYPES = %w(clients cookbooks containers data environments groups nodes roles sandboxes)
|
17
|
+
TOP_DATA_TYPES = %w(containers organizations users)
|
18
|
+
|
19
|
+
# ACL data paths for a partition are:
|
20
|
+
# / -> /acls/root
|
21
|
+
# /TYPE -> /acls/containers/TYPE
|
22
|
+
# /TYPE/NAME -> /acls/TYPE/NAME
|
23
|
+
#
|
24
|
+
# The root partition "/" has its own acls, so it looks like this:
|
25
|
+
#
|
26
|
+
# / -> /acls/root
|
27
|
+
# /users -> /acls/containers/users
|
28
|
+
# /organizations -> /acls/containers/organizations
|
29
|
+
# /users/schlansky -> /acls/users/schlansky
|
30
|
+
#
|
31
|
+
# Each organization is its own partition, so it looks like this:
|
32
|
+
#
|
33
|
+
# /organizations/blah -> /organizations/blah/acls/root
|
34
|
+
# /organizations/blah/roles -> /organizations/blah/acls/containers/roles
|
35
|
+
# /organizations/blah/roles/web -> /organizations/blah/acls/roles/web
|
36
|
+
# /organizations/ORG is its own partition. ACLs for anything under it follow
|
37
|
+
|
38
|
+
# This method takes a Chef REST path and returns the chef-zero path
|
39
|
+
# used to look up the ACL. If an object does not have an ACL directly,
|
40
|
+
# it will return nil. Paths like /organizations/ORG/data/bag/item will
|
41
|
+
# return nil, because it is the parent path (data/bag) that has an ACL.
|
42
|
+
def self.get_acl_data_path(path)
|
43
|
+
# Things under organizations have their own acls hierarchy
|
44
|
+
if path[0] == 'organizations' && path.size >= 2
|
45
|
+
under_org = partition_acl_data_path(path[2..-1], ORG_DATA_TYPES)
|
46
|
+
if under_org
|
47
|
+
path[0..1] + under_org
|
48
|
+
end
|
49
|
+
else
|
50
|
+
partition_acl_data_path(path, TOP_DATA_TYPES)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# Reverse transform from acl_data_path to path.
|
56
|
+
# /acls/root -> /
|
57
|
+
# /acls/** -> /**
|
58
|
+
# /organizations/ORG/acls/root -> /organizations/ORG
|
59
|
+
# /organizations/ORG/acls/** -> /organizations/ORG/**
|
60
|
+
#
|
61
|
+
# This means that /acls/containers/nodes maps to
|
62
|
+
# /containers/nodes, not /nodes.
|
63
|
+
#
|
64
|
+
def self.get_object_path(acl_data_path)
|
65
|
+
if acl_data_path[0] == 'acls'
|
66
|
+
if acl_data_path[1] == 'root'
|
67
|
+
[]
|
68
|
+
else
|
69
|
+
acl_data_path[1..-1]
|
70
|
+
end
|
71
|
+
elsif acl_data_path[0] == 'organizations' && acl_data_path[2] == 'acls'
|
72
|
+
if acl_data_path[3] == 'root'
|
73
|
+
acl_data_path[0..1]
|
74
|
+
else
|
75
|
+
acl_data_path[0..1] + acl_data_path[3..-1]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Method *assumes* acl_data_path is valid.
|
81
|
+
# /organizations/BLAH's parent is /organizations
|
82
|
+
#
|
83
|
+
# An example traversal up the whole tree:
|
84
|
+
# /organizations/foo/acls/nodes/mario ->
|
85
|
+
# /organizations/foo/acls/containers/nodes ->
|
86
|
+
# /organizations/foo/acls/containers/containers ->
|
87
|
+
# /organizations/foo/acls/root ->
|
88
|
+
# /acls/containers/organizations ->
|
89
|
+
# /acls/containers/containers ->
|
90
|
+
# /acls/root ->
|
91
|
+
# nil
|
92
|
+
def self.parent_acl_data_path(acl_data_path)
|
93
|
+
if acl_data_path[0] == 'organizations'
|
94
|
+
under_org = partition_parent_acl_data_path(acl_data_path[2..-1])
|
95
|
+
if under_org
|
96
|
+
acl_data_path[0..1] + under_org
|
97
|
+
else
|
98
|
+
# ACL data path is /organizations/X/acls/root; therefore parent is "/organizations"
|
99
|
+
[ 'acls', 'containers', 'organizations' ]
|
100
|
+
end
|
101
|
+
else
|
102
|
+
partition_parent_acl_data_path(acl_data_path)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
# /acls/root -> nil
|
109
|
+
# /acls/containers/containers -> /acls/root
|
110
|
+
# /acls/TYPE/X -> /acls/containers/TYPE
|
111
|
+
#
|
112
|
+
# Method *assumes* acl_data_path is valid.
|
113
|
+
# Returns nil if the path is /acls/root
|
114
|
+
def self.partition_parent_acl_data_path(acl_data_path)
|
115
|
+
if acl_data_path.size == 3
|
116
|
+
if acl_data_path == %w(acls containers containers)
|
117
|
+
[ 'acls', 'root' ]
|
118
|
+
else
|
119
|
+
[ 'acls', 'containers', acl_data_path[1]]
|
120
|
+
end
|
121
|
+
else
|
122
|
+
nil
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def self.partition_acl_data_path(path, data_types)
|
127
|
+
if path.size == 0
|
128
|
+
[ 'acls', 'root']
|
129
|
+
elsif data_types.include?(path[0])
|
130
|
+
if path.size == 0
|
131
|
+
[ 'acls', 'containers', path[0] ]
|
132
|
+
elsif path.size == 2
|
133
|
+
[ 'acls', path[0], path[1] ]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,240 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
require 'hashie/mash'
|
3
|
+
|
4
|
+
module ChefZero
|
5
|
+
module ChefData
|
6
|
+
module CookbookData
|
7
|
+
def self.to_hash(cookbook, name, version=nil)
|
8
|
+
frozen = false
|
9
|
+
if cookbook.has_key?(:frozen)
|
10
|
+
frozen = cookbook[:frozen]
|
11
|
+
cookbook = cookbook.dup
|
12
|
+
cookbook.delete(:frozen)
|
13
|
+
end
|
14
|
+
|
15
|
+
result = files_from(cookbook)
|
16
|
+
recipe_names = result[:recipes].map do |recipe|
|
17
|
+
recipe_name = recipe[:name][0..-2]
|
18
|
+
recipe_name == 'default' ? name : "#{name}::#{recipe_name}"
|
19
|
+
end
|
20
|
+
result[:metadata] = metadata_from(cookbook, name, version, recipe_names)
|
21
|
+
result[:name] = "#{name}-#{result[:metadata][:version]}"
|
22
|
+
result[:json_class] = 'Chef::CookbookVersion'
|
23
|
+
result[:cookbook_name] = name
|
24
|
+
result[:version] = result[:metadata][:version]
|
25
|
+
result[:chef_type] = 'cookbook_version'
|
26
|
+
result[:frozen?] = true if frozen
|
27
|
+
result
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.metadata_from(directory, name, version, recipe_names)
|
31
|
+
metadata = PretendCookbookMetadata.new(PretendCookbook.new(name, recipe_names))
|
32
|
+
# If both .rb and .json exist, read .rb
|
33
|
+
# TODO if recipes has 3 recipes in it, and the Ruby/JSON has only one, should
|
34
|
+
# the resulting recipe list have 1, or 3-4 recipes in it?
|
35
|
+
if has_child(directory, 'metadata.rb')
|
36
|
+
begin
|
37
|
+
file = filename(directory, 'metadata.rb') || "(#{name}/metadata.rb)"
|
38
|
+
metadata.instance_eval(read_file(directory, 'metadata.rb'), file)
|
39
|
+
rescue
|
40
|
+
ChefZero::Log.error("Error loading cookbook #{name}: #{$!}\n #{$!.backtrace.join("\n ")}")
|
41
|
+
end
|
42
|
+
elsif has_child(directory, 'metadata.json')
|
43
|
+
metadata.from_json(read_file(directory, 'metadata.json'))
|
44
|
+
end
|
45
|
+
result = {}
|
46
|
+
metadata.to_hash.each_pair do |key,value|
|
47
|
+
result[key.to_sym] = value
|
48
|
+
end
|
49
|
+
result[:version] = version if version
|
50
|
+
result
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# Just enough cookbook to make a Metadata object
|
56
|
+
class PretendCookbook
|
57
|
+
def initialize(name, fully_qualified_recipe_names)
|
58
|
+
@name = name
|
59
|
+
@fully_qualified_recipe_names = fully_qualified_recipe_names
|
60
|
+
end
|
61
|
+
attr_reader :name, :fully_qualified_recipe_names
|
62
|
+
end
|
63
|
+
|
64
|
+
# Handles loading configuration values from a Chef config file
|
65
|
+
#
|
66
|
+
# @author Justin Campbell <justin.campbell@riotgames.com>
|
67
|
+
class PretendCookbookMetadata < Hash
|
68
|
+
# @param [String] path
|
69
|
+
def initialize(cookbook)
|
70
|
+
self.name(cookbook.name)
|
71
|
+
self.recipes(cookbook.fully_qualified_recipe_names)
|
72
|
+
%w(attributes grouping dependencies supports recommendations suggestions conflicting providing replacing recipes).each do |hash_arg|
|
73
|
+
self[hash_arg.to_sym] = Hashie::Mash.new
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def from_json(json)
|
78
|
+
self.merge!(JSON.parse(json))
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def depends(cookbook, *version_constraints)
|
84
|
+
cookbook_arg(:dependencies, cookbook, version_constraints)
|
85
|
+
end
|
86
|
+
|
87
|
+
def supports(cookbook, *version_constraints)
|
88
|
+
cookbook_arg(:supports, cookbook, version_constraints)
|
89
|
+
end
|
90
|
+
|
91
|
+
def recommends(cookbook, *version_constraints)
|
92
|
+
cookbook_arg(:recommendations, cookbook, version_constraints)
|
93
|
+
end
|
94
|
+
|
95
|
+
def suggests(cookbook, *version_constraints)
|
96
|
+
cookbook_arg(:suggestions, cookbook, version_constraints)
|
97
|
+
end
|
98
|
+
|
99
|
+
def conflicts(cookbook, *version_constraints)
|
100
|
+
cookbook_arg(:conflicting, cookbook, version_constraints)
|
101
|
+
end
|
102
|
+
|
103
|
+
def provides(cookbook, *version_constraints)
|
104
|
+
cookbook_arg(:providing, cookbook, version_constraints)
|
105
|
+
end
|
106
|
+
|
107
|
+
def replaces(cookbook, *version_constraints)
|
108
|
+
cookbook_arg(:replacing, cookbook, version_constraints)
|
109
|
+
end
|
110
|
+
|
111
|
+
def recipe(recipe, description)
|
112
|
+
self[:recipes][recipe] = description
|
113
|
+
end
|
114
|
+
|
115
|
+
def attribute(name, options)
|
116
|
+
self[:attributes][name] = options
|
117
|
+
end
|
118
|
+
|
119
|
+
def grouping(name, options)
|
120
|
+
self[:grouping][name] = options
|
121
|
+
end
|
122
|
+
|
123
|
+
def cookbook_arg(key, cookbook, version_constraints)
|
124
|
+
self[key][cookbook] = version_constraints.first || ">= 0.0.0"
|
125
|
+
end
|
126
|
+
|
127
|
+
def method_missing(key, value = nil)
|
128
|
+
if value.nil?
|
129
|
+
self[key.to_sym]
|
130
|
+
else
|
131
|
+
store key.to_sym, value
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.files_from(directory)
|
137
|
+
# TODO some support .rb only
|
138
|
+
result = {
|
139
|
+
:attributes => load_child_files(directory, 'attributes', false),
|
140
|
+
:definitions => load_child_files(directory, 'definitions', false),
|
141
|
+
:recipes => load_child_files(directory, 'recipes', false),
|
142
|
+
:libraries => load_child_files(directory, 'libraries', false),
|
143
|
+
:templates => load_child_files(directory, 'templates', true),
|
144
|
+
:files => load_child_files(directory, 'files', true),
|
145
|
+
:resources => load_child_files(directory, 'resources', true),
|
146
|
+
:providers => load_child_files(directory, 'providers', true),
|
147
|
+
:root_files => load_files(directory, false)
|
148
|
+
}
|
149
|
+
set_specificity(result[:templates])
|
150
|
+
set_specificity(result[:files])
|
151
|
+
result
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.has_child(directory, name)
|
155
|
+
if directory.is_a?(Hash)
|
156
|
+
directory.has_key?(name)
|
157
|
+
else
|
158
|
+
directory.child(name).exists?
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def self.read_file(directory, name)
|
163
|
+
if directory.is_a?(Hash)
|
164
|
+
directory[name]
|
165
|
+
else
|
166
|
+
directory.child(name).read
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def self.filename(directory, name)
|
171
|
+
if directory.respond_to?(:file_path)
|
172
|
+
File.join(directory.file_path, name)
|
173
|
+
else
|
174
|
+
nil
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def self.get_directory(directory, name)
|
179
|
+
if directory.is_a?(Hash)
|
180
|
+
directory[name].is_a?(Hash) ? directory[name] : nil
|
181
|
+
else
|
182
|
+
result = directory.child(name)
|
183
|
+
result.dir? ? result : nil
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def self.list(directory)
|
188
|
+
if directory.is_a?(Hash)
|
189
|
+
directory.keys
|
190
|
+
else
|
191
|
+
directory.children.map { |c| c.name }
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def self.load_child_files(parent, key, recursive)
|
196
|
+
result = load_files(get_directory(parent, key), recursive)
|
197
|
+
result.each do |file|
|
198
|
+
file[:path] = "#{key}/#{file[:path]}"
|
199
|
+
end
|
200
|
+
result
|
201
|
+
end
|
202
|
+
|
203
|
+
def self.load_files(directory, recursive)
|
204
|
+
result = []
|
205
|
+
if directory
|
206
|
+
list(directory).each do |child_name|
|
207
|
+
dir = get_directory(directory, child_name)
|
208
|
+
if dir
|
209
|
+
if recursive
|
210
|
+
result += load_child_files(directory, child_name, recursive)
|
211
|
+
end
|
212
|
+
else
|
213
|
+
result += load_file(read_file(directory, child_name), child_name)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
result
|
218
|
+
end
|
219
|
+
|
220
|
+
def self.load_file(value, name)
|
221
|
+
[{
|
222
|
+
:name => name,
|
223
|
+
:path => name,
|
224
|
+
:checksum => Digest::MD5.hexdigest(value),
|
225
|
+
:specificity => 'default'
|
226
|
+
}]
|
227
|
+
end
|
228
|
+
|
229
|
+
def self.set_specificity(files)
|
230
|
+
files.each do |file|
|
231
|
+
parts = file[:path].split('/')
|
232
|
+
raise "Only directories are allowed directly under templates or files: #{file[:path]}" if parts.size == 2
|
233
|
+
file[:specificity] = parts[1]
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
CookbookData = ChefData::CookbookData
|
240
|
+
end
|