chef-zero 2.2.1 → 3.0.0.rc.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Stories in Ready](https://badge.waffle.io/opscode/chef-zero.png?label=ready&title=Ready)](https://waffle.io/opscode/chef-zero)[![Stories in Progress](https://badge.waffle.io/opscode/chef-zero.png?label=in+progress&title=In+Progress)](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
|