clc-cheffish 0.8.clc
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 +7 -0
- data/LICENSE +201 -0
- data/README.md +4 -0
- data/Rakefile +23 -0
- data/lib/chef/provider/chef_acl.rb +434 -0
- data/lib/chef/provider/chef_client.rb +48 -0
- data/lib/chef/provider/chef_container.rb +50 -0
- data/lib/chef/provider/chef_data_bag.rb +50 -0
- data/lib/chef/provider/chef_data_bag_item.rb +273 -0
- data/lib/chef/provider/chef_environment.rb +78 -0
- data/lib/chef/provider/chef_group.rb +78 -0
- data/lib/chef/provider/chef_mirror.rb +138 -0
- data/lib/chef/provider/chef_node.rb +82 -0
- data/lib/chef/provider/chef_organization.rb +150 -0
- data/lib/chef/provider/chef_resolved_cookbooks.rb +41 -0
- data/lib/chef/provider/chef_role.rb +79 -0
- data/lib/chef/provider/chef_user.rb +53 -0
- data/lib/chef/provider/private_key.rb +219 -0
- data/lib/chef/provider/public_key.rb +82 -0
- data/lib/chef/resource/chef_acl.rb +65 -0
- data/lib/chef/resource/chef_client.rb +44 -0
- data/lib/chef/resource/chef_container.rb +18 -0
- data/lib/chef/resource/chef_data_bag.rb +18 -0
- data/lib/chef/resource/chef_data_bag_item.rb +114 -0
- data/lib/chef/resource/chef_environment.rb +71 -0
- data/lib/chef/resource/chef_group.rb +49 -0
- data/lib/chef/resource/chef_mirror.rb +47 -0
- data/lib/chef/resource/chef_node.rb +18 -0
- data/lib/chef/resource/chef_organization.rb +64 -0
- data/lib/chef/resource/chef_resolved_cookbooks.rb +31 -0
- data/lib/chef/resource/chef_role.rb +104 -0
- data/lib/chef/resource/chef_user.rb +51 -0
- data/lib/chef/resource/private_key.rb +44 -0
- data/lib/chef/resource/public_key.rb +21 -0
- data/lib/cheffish.rb +222 -0
- data/lib/cheffish/actor_provider_base.rb +131 -0
- data/lib/cheffish/basic_chef_client.rb +115 -0
- data/lib/cheffish/chef_provider_base.rb +231 -0
- data/lib/cheffish/chef_run_data.rb +19 -0
- data/lib/cheffish/chef_run_listener.rb +28 -0
- data/lib/cheffish/key_formatter.rb +109 -0
- data/lib/cheffish/merged_config.rb +94 -0
- data/lib/cheffish/recipe_dsl.rb +147 -0
- data/lib/cheffish/server_api.rb +52 -0
- data/lib/cheffish/version.rb +3 -0
- data/lib/cheffish/with_pattern.rb +21 -0
- data/spec/functional/fingerprint_spec.rb +64 -0
- data/spec/functional/merged_config_spec.rb +20 -0
- data/spec/integration/chef_acl_spec.rb +914 -0
- data/spec/integration/chef_client_spec.rb +110 -0
- data/spec/integration/chef_container_spec.rb +34 -0
- data/spec/integration/chef_group_spec.rb +324 -0
- data/spec/integration/chef_mirror_spec.rb +244 -0
- data/spec/integration/chef_node_spec.rb +211 -0
- data/spec/integration/chef_organization_spec.rb +244 -0
- data/spec/integration/chef_user_spec.rb +90 -0
- data/spec/integration/private_key_spec.rb +446 -0
- data/spec/integration/recipe_dsl_spec.rb +29 -0
- data/spec/support/key_support.rb +29 -0
- data/spec/support/repository_support.rb +103 -0
- data/spec/support/spec_support.rb +176 -0
- data/spec/unit/get_private_key_spec.rb +93 -0
- metadata +162 -0
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'cheffish/key_formatter'
|
2
|
+
require 'cheffish/chef_provider_base'
|
3
|
+
|
4
|
+
class Cheffish::ActorProviderBase < Cheffish::ChefProviderBase
|
5
|
+
|
6
|
+
def create_actor
|
7
|
+
if new_resource.before
|
8
|
+
new_resource.before.call(new_resource)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Create or update the client/user
|
12
|
+
current_public_key = new_json['public_key']
|
13
|
+
differences = json_differences(current_json, new_json)
|
14
|
+
if current_resource_exists?
|
15
|
+
# Update the actor if it's different
|
16
|
+
if differences.size > 0
|
17
|
+
description = [ "update #{actor_type} #{new_resource.name} at #{actor_path}" ] + differences
|
18
|
+
converge_by description do
|
19
|
+
result = rest.put("#{actor_path}/#{new_resource.name}", normalize_for_put(new_json))
|
20
|
+
current_public_key, current_public_key_format = Cheffish::KeyFormatter.decode(result['public_key']) if result['public_key']
|
21
|
+
end
|
22
|
+
end
|
23
|
+
else
|
24
|
+
# Create the actor if it's missing
|
25
|
+
if !new_public_key
|
26
|
+
raise "You must specify a public key to create a #{actor_type}! Use the private_key resource to create a key, and pass it in with source_key_path."
|
27
|
+
end
|
28
|
+
description = [ "create #{actor_type} #{new_resource.name} at #{actor_path}" ] + differences
|
29
|
+
converge_by description do
|
30
|
+
result = rest.post("#{actor_path}", normalize_for_post(new_json))
|
31
|
+
current_public_key, current_public_key_format = Cheffish::KeyFormatter.decode(result['public_key']) if result['public_key']
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Write out the public key
|
36
|
+
if new_resource.output_key_path
|
37
|
+
# TODO use inline_resource
|
38
|
+
key_content = Cheffish::KeyFormatter.encode(current_public_key, { :format => new_resource.output_key_format })
|
39
|
+
if !current_resource.output_key_path
|
40
|
+
action = 'create'
|
41
|
+
elsif key_content != IO.read(current_resource.output_key_path)
|
42
|
+
action = 'overwrite'
|
43
|
+
else
|
44
|
+
action = nil
|
45
|
+
end
|
46
|
+
if action
|
47
|
+
converge_by "#{action} public key #{new_resource.output_key_path}" do
|
48
|
+
IO.write(new_resource.output_key_path, key_content)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
# TODO permissions?
|
52
|
+
end
|
53
|
+
|
54
|
+
if new_resource.after
|
55
|
+
new_resource.after.call(self, new_json, server_private_key, server_public_key)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def delete_actor
|
60
|
+
if current_resource_exists?
|
61
|
+
converge_by "delete #{actor_type} #{new_resource.name} at #{actor_path}" do
|
62
|
+
rest.delete("#{actor_path}/#{new_resource.name}")
|
63
|
+
Chef::Log.info("#{new_resource} deleted #{actor_type} #{new_resource.name} at #{rest.url}")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
if current_resource.output_key_path
|
67
|
+
converge_by "delete public key #{current_resource.output_key_path}" do
|
68
|
+
::File.unlink(current_resource.output_key_path)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def new_public_key
|
74
|
+
@new_public_key ||= begin
|
75
|
+
if new_resource.source_key
|
76
|
+
if new_resource.source_key.is_a?(String)
|
77
|
+
key, key_format = Cheffish::KeyFormatter.decode(new_resource.source_key)
|
78
|
+
|
79
|
+
if key.private?
|
80
|
+
key.public_key
|
81
|
+
else
|
82
|
+
key
|
83
|
+
end
|
84
|
+
elsif new_resource.source_key.private?
|
85
|
+
new_resource.source_key.public_key
|
86
|
+
else
|
87
|
+
new_resource.source_key
|
88
|
+
end
|
89
|
+
elsif new_resource.source_key_path
|
90
|
+
source_key_path = new_resource.source_key_path
|
91
|
+
if Pathname.new(source_key_path).relative?
|
92
|
+
source_key_str, source_key_path = Cheffish.get_private_key_with_path(source_key_path, run_context.config)
|
93
|
+
else
|
94
|
+
source_key_str = IO.read(source_key_path)
|
95
|
+
end
|
96
|
+
source_key, source_key_format = Cheffish::KeyFormatter.decode(source_key_str, new_resource.source_key_pass_phrase, source_key_path)
|
97
|
+
if source_key.private?
|
98
|
+
source_key.public_key
|
99
|
+
else
|
100
|
+
source_key
|
101
|
+
end
|
102
|
+
else
|
103
|
+
nil
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def augment_new_json(json)
|
109
|
+
if new_public_key
|
110
|
+
json['public_key'] = new_public_key.to_pem
|
111
|
+
end
|
112
|
+
json
|
113
|
+
end
|
114
|
+
|
115
|
+
def load_current_resource
|
116
|
+
begin
|
117
|
+
json = rest.get("#{actor_path}/#{new_resource.name}")
|
118
|
+
@current_resource = json_to_resource(json)
|
119
|
+
rescue Net::HTTPServerException => e
|
120
|
+
if e.response.code == "404"
|
121
|
+
@current_resource = not_found_resource
|
122
|
+
else
|
123
|
+
raise
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
if new_resource.output_key_path && ::File.exist?(new_resource.output_key_path)
|
128
|
+
current_resource.output_key_path = new_resource.output_key_path
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'cheffish/version'
|
2
|
+
require 'chef/dsl/recipe'
|
3
|
+
require 'chef/event_dispatch/base'
|
4
|
+
require 'chef/event_dispatch/dispatcher'
|
5
|
+
require 'chef/node'
|
6
|
+
require 'chef/run_context'
|
7
|
+
require 'chef/runner'
|
8
|
+
require 'forwardable'
|
9
|
+
require 'chef/providers'
|
10
|
+
require 'chef/resources'
|
11
|
+
|
12
|
+
module Cheffish
|
13
|
+
class BasicChefClient
|
14
|
+
include Chef::DSL::Recipe
|
15
|
+
|
16
|
+
def initialize(node = nil, events = nil)
|
17
|
+
if !node
|
18
|
+
node = Chef::Node.new
|
19
|
+
node.name 'basic_chef_client'
|
20
|
+
node.automatic[:platform] = 'basic_chef_client'
|
21
|
+
node.automatic[:platform_version] = Cheffish::VERSION
|
22
|
+
end
|
23
|
+
|
24
|
+
@event_catcher = BasicChefClientEvents.new
|
25
|
+
dispatcher = Chef::EventDispatch::Dispatcher.new(@event_catcher)
|
26
|
+
dispatcher.register(events) if events
|
27
|
+
@run_context = Chef::RunContext.new(node, {}, dispatcher)
|
28
|
+
@updated = []
|
29
|
+
@cookbook_name = 'basic_chef_client'
|
30
|
+
end
|
31
|
+
|
32
|
+
extend Forwardable
|
33
|
+
|
34
|
+
# Stuff recipes need
|
35
|
+
attr_reader :run_context
|
36
|
+
attr_accessor :cookbook_name
|
37
|
+
attr_accessor :recipe_name
|
38
|
+
def_delegators :@run_context, :resource_collection, :immediate_notifications, :delayed_notifications
|
39
|
+
|
40
|
+
def add_resource(resource)
|
41
|
+
resource.run_context = run_context
|
42
|
+
run_context.resource_collection.insert(resource)
|
43
|
+
end
|
44
|
+
|
45
|
+
def load_block(&block)
|
46
|
+
@recipe_name = 'block'
|
47
|
+
instance_eval(&block)
|
48
|
+
end
|
49
|
+
|
50
|
+
def converge
|
51
|
+
Chef::Runner.new(self).converge
|
52
|
+
end
|
53
|
+
|
54
|
+
def updates
|
55
|
+
@event_catcher.updates
|
56
|
+
end
|
57
|
+
|
58
|
+
def updated?
|
59
|
+
@event_catcher.updates.size > 0
|
60
|
+
end
|
61
|
+
|
62
|
+
# Builds a resource sans context, which can be later used in a new client's
|
63
|
+
# add_resource() method.
|
64
|
+
def self.build_resource(type, name, created_at=nil, &resource_attrs_block)
|
65
|
+
created_at ||= caller[0]
|
66
|
+
result = BasicChefClient.new.build_resource(type, name, created_at, &resource_attrs_block)
|
67
|
+
result
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.inline_resource(provider, provider_action, *resources, &block)
|
71
|
+
events = ProviderEventForwarder.new(provider, provider_action)
|
72
|
+
client = BasicChefClient.new(provider.node, events)
|
73
|
+
resources.each do |resource|
|
74
|
+
client.add_resource(resource)
|
75
|
+
end
|
76
|
+
client.load_block(&block) if block
|
77
|
+
client.converge
|
78
|
+
client.updated?
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.converge_block(node = nil, events = nil, &block)
|
82
|
+
client = BasicChefClient.new(node, events)
|
83
|
+
client.load_block(&block)
|
84
|
+
client.converge
|
85
|
+
client.updated?
|
86
|
+
end
|
87
|
+
|
88
|
+
class BasicChefClientEvents < Chef::EventDispatch::Base
|
89
|
+
def initialize
|
90
|
+
@updates = []
|
91
|
+
end
|
92
|
+
|
93
|
+
attr_reader :updates
|
94
|
+
|
95
|
+
# Called after a resource has been completely converged.
|
96
|
+
def resource_updated(resource, action)
|
97
|
+
updates << [ resource, action ]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class ProviderEventForwarder < Chef::EventDispatch::Base
|
102
|
+
def initialize(provider, provider_action)
|
103
|
+
@provider = provider
|
104
|
+
@provider_action = provider_action
|
105
|
+
end
|
106
|
+
|
107
|
+
attr_reader :provider
|
108
|
+
attr_reader :provider_action
|
109
|
+
|
110
|
+
def resource_update_applied(resource, action, update)
|
111
|
+
provider.run_context.events.resource_update_applied(provider.new_resource, provider_action, update)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,231 @@
|
|
1
|
+
require 'chef/config'
|
2
|
+
require 'chef/run_list'
|
3
|
+
require 'chef/provider/lwrp_base'
|
4
|
+
|
5
|
+
module Cheffish
|
6
|
+
class ChefProviderBase < Chef::Provider::LWRPBase
|
7
|
+
def rest
|
8
|
+
@rest ||= Cheffish.chef_server_api(new_resource.chef_server)
|
9
|
+
end
|
10
|
+
|
11
|
+
def current_resource_exists?
|
12
|
+
Array(current_resource.action) != [ :delete ]
|
13
|
+
end
|
14
|
+
|
15
|
+
def not_found_resource
|
16
|
+
resource = resource_class.new(new_resource.name, run_context)
|
17
|
+
resource.action :delete
|
18
|
+
resource
|
19
|
+
end
|
20
|
+
|
21
|
+
def normalize_for_put(json)
|
22
|
+
data_handler.normalize_for_put(json, fake_entry)
|
23
|
+
end
|
24
|
+
|
25
|
+
def normalize_for_post(json)
|
26
|
+
data_handler.normalize_for_post(json, fake_entry)
|
27
|
+
end
|
28
|
+
|
29
|
+
def new_json
|
30
|
+
@new_json ||= begin
|
31
|
+
if new_resource.complete
|
32
|
+
result = normalize(resource_to_json(new_resource))
|
33
|
+
else
|
34
|
+
# If resource is incomplete, use current json to fill any holes
|
35
|
+
result = Chef::Mixin::DeepMerge.hash_only_merge(current_json, resource_to_json(new_resource))
|
36
|
+
end
|
37
|
+
augment_new_json(result)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Meant to be overridden
|
42
|
+
def augment_new_json(json)
|
43
|
+
json
|
44
|
+
end
|
45
|
+
|
46
|
+
def current_json
|
47
|
+
@current_json ||= begin
|
48
|
+
result = normalize(resource_to_json(current_resource))
|
49
|
+
result = augment_current_json(result)
|
50
|
+
result
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Meant to be overridden
|
55
|
+
def augment_current_json(json)
|
56
|
+
json
|
57
|
+
end
|
58
|
+
|
59
|
+
def resource_to_json(resource)
|
60
|
+
json = resource.raw_json || {}
|
61
|
+
keys.each do |json_key, resource_key|
|
62
|
+
value = resource.send(resource_key)
|
63
|
+
json[json_key] = value if value
|
64
|
+
end
|
65
|
+
json
|
66
|
+
end
|
67
|
+
|
68
|
+
def json_to_resource(json)
|
69
|
+
resource = resource_class.new(new_resource.name, run_context)
|
70
|
+
keys.each do |json_key, resource_key|
|
71
|
+
resource.send(resource_key, json.delete(json_key))
|
72
|
+
end
|
73
|
+
# Set the leftover to raw_json
|
74
|
+
resource.raw_json json
|
75
|
+
resource
|
76
|
+
end
|
77
|
+
|
78
|
+
def normalize(json)
|
79
|
+
data_handler.normalize(json, fake_entry)
|
80
|
+
end
|
81
|
+
|
82
|
+
def json_differences(old_json, new_json, print_values=true, name = '', result = nil)
|
83
|
+
result ||= []
|
84
|
+
json_differences_internal(old_json, new_json, print_values, name, result)
|
85
|
+
result
|
86
|
+
end
|
87
|
+
|
88
|
+
def json_differences_internal(old_json, new_json, print_values, name, result)
|
89
|
+
if old_json.kind_of?(Hash) && new_json.kind_of?(Hash)
|
90
|
+
removed_keys = old_json.keys.inject({}) { |hash, key| hash[key] = true; hash }
|
91
|
+
new_json.each_pair do |new_key, new_value|
|
92
|
+
if old_json.has_key?(new_key)
|
93
|
+
removed_keys.delete(new_key)
|
94
|
+
if new_value != old_json[new_key]
|
95
|
+
json_differences_internal(old_json[new_key], new_value, print_values, name == '' ? new_key : "#{name}.#{new_key}", result)
|
96
|
+
end
|
97
|
+
else
|
98
|
+
if print_values
|
99
|
+
result << " add #{name == '' ? new_key : "#{name}.#{new_key}"} = #{new_value.inspect}"
|
100
|
+
else
|
101
|
+
result << " add #{name == '' ? new_key : "#{name}.#{new_key}"}"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
removed_keys.keys.each do |removed_key|
|
106
|
+
result << " remove #{name == '' ? removed_key : "#{name}.#{removed_key}"}"
|
107
|
+
end
|
108
|
+
else
|
109
|
+
old_json = old_json.to_s if old_json.kind_of?(Symbol)
|
110
|
+
new_json = new_json.to_s if new_json.kind_of?(Symbol)
|
111
|
+
if old_json != new_json
|
112
|
+
if print_values
|
113
|
+
result << " update #{name} from #{old_json.inspect} to #{new_json.inspect}"
|
114
|
+
else
|
115
|
+
result << " update #{name}"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def apply_modifiers(modifiers, json)
|
122
|
+
return json if !modifiers || modifiers.size == 0
|
123
|
+
|
124
|
+
# If the attributes have nothing, set them to {} so we have something to add to
|
125
|
+
if json
|
126
|
+
json = Marshal.load(Marshal.dump(json)) # Deep copy
|
127
|
+
else
|
128
|
+
json = {}
|
129
|
+
end
|
130
|
+
|
131
|
+
modifiers.each do |path, value|
|
132
|
+
path = [path] if !path.kind_of?(Array)
|
133
|
+
path = path.map { |path_part| path_part.to_s }
|
134
|
+
parent = path[0..-2].inject(json) { |hash, path_part| hash ? hash[path_part] : nil }
|
135
|
+
existing_value = parent ? parent[path[-1]] : nil
|
136
|
+
|
137
|
+
if value.is_a?(Proc)
|
138
|
+
value = value.call(existing_value)
|
139
|
+
end
|
140
|
+
if value == :delete
|
141
|
+
parent.delete(path[-1]) if parent
|
142
|
+
# TODO clean up parent chain if hash is completely emptied
|
143
|
+
else
|
144
|
+
if !parent
|
145
|
+
# Create parent if necessary
|
146
|
+
parent = path[0..-2].inject(json) do |hash, path_part|
|
147
|
+
hash[path_part] = {} if !hash[path_part]
|
148
|
+
hash[path_part]
|
149
|
+
end
|
150
|
+
end
|
151
|
+
parent[path[-1]] = value
|
152
|
+
end
|
153
|
+
end
|
154
|
+
json
|
155
|
+
end
|
156
|
+
|
157
|
+
def apply_run_list_modifiers(add_to_run_list, delete_from_run_list, run_list)
|
158
|
+
return run_list if (!add_to_run_list || add_to_run_list.size == 0) && (!delete_from_run_list || !delete_from_run_list.size)
|
159
|
+
delete_from_run_list ||= []
|
160
|
+
add_to_run_list ||= []
|
161
|
+
|
162
|
+
run_list = Chef::RunList.new(*run_list)
|
163
|
+
|
164
|
+
result = []
|
165
|
+
add_to_run_list_index = 0
|
166
|
+
run_list_index = 0
|
167
|
+
while run_list_index < run_list.run_list_items.size do
|
168
|
+
# See if the desired run list has this item
|
169
|
+
found_desired = add_to_run_list.index { |item| same_run_list_item(item, run_list[run_list_index]) }
|
170
|
+
if found_desired
|
171
|
+
# If so, copy all items up to that desired run list (to preserve order).
|
172
|
+
# If a run list item is out of order (run_list = X, B, Y, A, Z and desired = A, B)
|
173
|
+
# then this will give us X, A, B. When A is found later, nothing will be copied
|
174
|
+
# because found_desired will be less than add_to_run_list_index. The result will
|
175
|
+
# be X, A, B, Y, Z.
|
176
|
+
if found_desired >= add_to_run_list_index
|
177
|
+
result += add_to_run_list[add_to_run_list_index..found_desired].map { |item| item.to_s }
|
178
|
+
add_to_run_list_index = found_desired+1
|
179
|
+
end
|
180
|
+
else
|
181
|
+
# If not, just copy it in
|
182
|
+
unless delete_from_run_list.index { |item| same_run_list_item(item, run_list[run_list_index]) }
|
183
|
+
result << run_list[run_list_index].to_s
|
184
|
+
end
|
185
|
+
end
|
186
|
+
run_list_index += 1
|
187
|
+
end
|
188
|
+
|
189
|
+
# Copy any remaining desired items at the end
|
190
|
+
result += add_to_run_list[add_to_run_list_index..-1].map { |item| item.to_s }
|
191
|
+
result
|
192
|
+
end
|
193
|
+
|
194
|
+
def same_run_list_item(a, b)
|
195
|
+
a_name = a.name
|
196
|
+
b_name = b.name
|
197
|
+
# Handle "a::default" being the same as "a"
|
198
|
+
if a.type == :recipe && a_name =~ /(.+)::default$/
|
199
|
+
a_name = $1
|
200
|
+
elsif b.type == :recipe && b_name =~ /(.+)::default$/
|
201
|
+
b_name = $1
|
202
|
+
end
|
203
|
+
|
204
|
+
a_name == b_name && a.type == b.type # We want to replace things with same name and different version
|
205
|
+
end
|
206
|
+
|
207
|
+
private
|
208
|
+
|
209
|
+
# Needed to be able to use DataHandler classes
|
210
|
+
def fake_entry
|
211
|
+
FakeEntry.new("#{new_resource.send(keys.values.first)}.json")
|
212
|
+
end
|
213
|
+
|
214
|
+
class FakeEntry
|
215
|
+
def initialize(name, parent = nil)
|
216
|
+
@name = name
|
217
|
+
@parent = parent
|
218
|
+
@org = nil
|
219
|
+
end
|
220
|
+
|
221
|
+
attr_reader :name
|
222
|
+
attr_reader :parent
|
223
|
+
attr_reader :org
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
# We are not interested in Chef's cloning behavior here.
|
228
|
+
def load_prior_resource
|
229
|
+
Chef::Log.debug("Overloading #{resource_name}.load_prior_resource with NOOP")
|
230
|
+
end
|
231
|
+
end
|