cheffish 1.6.0 → 2.0.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/cheffish.gemspec +1 -0
  3. data/lib/chef/resource/chef_acl.rb +440 -20
  4. data/lib/chef/resource/chef_client.rb +50 -25
  5. data/lib/chef/resource/chef_container.rb +44 -11
  6. data/lib/chef/resource/chef_data_bag.rb +43 -10
  7. data/lib/chef/resource/chef_data_bag_item.rb +292 -82
  8. data/lib/chef/resource/chef_environment.rb +79 -27
  9. data/lib/chef/resource/chef_group.rb +77 -40
  10. data/lib/chef/resource/chef_mirror.rb +170 -21
  11. data/lib/chef/resource/chef_node.rb +77 -11
  12. data/lib/chef/resource/chef_organization.rb +153 -43
  13. data/lib/chef/resource/chef_resolved_cookbooks.rb +40 -9
  14. data/lib/chef/resource/chef_role.rb +81 -29
  15. data/lib/chef/resource/chef_user.rb +64 -33
  16. data/lib/chef/resource/private_key.rb +230 -17
  17. data/lib/chef/resource/public_key.rb +88 -9
  18. data/lib/cheffish/array_property.rb +29 -0
  19. data/lib/cheffish/base_resource.rb +254 -0
  20. data/lib/cheffish/chef_actor_base.rb +135 -0
  21. data/lib/cheffish/node_properties.rb +107 -0
  22. data/lib/cheffish/recipe_dsl.rb +0 -14
  23. data/lib/cheffish/version.rb +1 -1
  24. data/lib/cheffish.rb +4 -108
  25. data/spec/integration/chef_acl_spec.rb +0 -2
  26. data/spec/integration/chef_client_spec.rb +0 -1
  27. data/spec/integration/chef_container_spec.rb +0 -2
  28. data/spec/integration/chef_group_spec.rb +0 -2
  29. data/spec/integration/chef_mirror_spec.rb +0 -2
  30. data/spec/integration/chef_node_spec.rb +0 -2
  31. data/spec/integration/chef_organization_spec.rb +1 -3
  32. data/spec/integration/chef_role_spec.rb +0 -2
  33. data/spec/integration/chef_user_spec.rb +0 -2
  34. data/spec/integration/private_key_spec.rb +0 -4
  35. data/spec/integration/recipe_dsl_spec.rb +0 -2
  36. data/spec/support/spec_support.rb +0 -1
  37. data/spec/unit/get_private_key_spec.rb +13 -0
  38. metadata +22 -20
  39. data/lib/chef/provider/chef_acl.rb +0 -446
  40. data/lib/chef/provider/chef_client.rb +0 -53
  41. data/lib/chef/provider/chef_container.rb +0 -55
  42. data/lib/chef/provider/chef_data_bag.rb +0 -55
  43. data/lib/chef/provider/chef_data_bag_item.rb +0 -278
  44. data/lib/chef/provider/chef_environment.rb +0 -83
  45. data/lib/chef/provider/chef_group.rb +0 -83
  46. data/lib/chef/provider/chef_mirror.rb +0 -169
  47. data/lib/chef/provider/chef_node.rb +0 -87
  48. data/lib/chef/provider/chef_organization.rb +0 -155
  49. data/lib/chef/provider/chef_resolved_cookbooks.rb +0 -46
  50. data/lib/chef/provider/chef_role.rb +0 -84
  51. data/lib/chef/provider/chef_user.rb +0 -59
  52. data/lib/chef/provider/private_key.rb +0 -225
  53. data/lib/chef/provider/public_key.rb +0 -88
  54. data/lib/cheffish/actor_provider_base.rb +0 -131
  55. data/lib/cheffish/chef_provider_base.rb +0 -246
@@ -1,18 +1,15 @@
1
- require 'chef/resource/lwrp_base'
1
+ require 'cheffish/base_resource'
2
+ require 'chef_zero'
2
3
 
3
4
  class Chef
4
5
  class Resource
5
- class ChefResolvedCookbooks < Chef::Resource::LWRPBase
6
- self.resource_name = 'chef_resolved_cookbooks'
7
-
8
- actions :resolve, :nothing
9
- default_action :resolve
6
+ class ChefResolvedCookbooks < Cheffish::BaseResource
7
+ resource_name :chef_resolved_cookbooks
10
8
 
11
9
  def initialize(*args)
12
10
  super
13
11
  require 'berkshelf'
14
12
  berksfile Berkshelf::Berksfile.new('/tmp/Berksfile')
15
- chef_server run_context.cheffish.current_chef_server
16
13
  @cookbooks_from = []
17
14
  end
18
15
 
@@ -28,8 +25,42 @@ class Chef
28
25
  end
29
26
  end
30
27
 
31
- attribute :berksfile
32
- attribute :chef_server
28
+ property :berksfile
29
+
30
+ action :resolve do
31
+ new_resource.cookbooks_from.each do |path|
32
+ ::Dir.entries(path).each do |name|
33
+ if ::File.directory?(::File.join(path, name)) && name != '.' && name != '..'
34
+ new_resource.berksfile.cookbook name, :path => ::File.join(path, name)
35
+ end
36
+ end
37
+ end
38
+
39
+ new_resource.berksfile.install
40
+
41
+ # Ridley really really wants a key :/
42
+ if new_resource.chef_server[:options][:signing_key_filename]
43
+ new_resource.berksfile.upload(
44
+ :server_url => new_resource.chef_server[:chef_server_url],
45
+ :client_name => new_resource.chef_server[:options][:client_name],
46
+ :client_key => new_resource.chef_server[:options][:signing_key_filename])
47
+ else
48
+ file = Tempfile.new('privatekey')
49
+ begin
50
+ file.write(ChefZero::PRIVATE_KEY)
51
+ file.close
52
+
53
+ new_resource.berksfile.upload(
54
+ :server_url => new_resource.chef_server[:chef_server_url],
55
+ :client_name => new_resource.chef_server[:options][:client_name] || 'me',
56
+ :client_key => file.path)
57
+
58
+ ensure
59
+ file.close
60
+ file.unlink
61
+ end
62
+ end
63
+ end
33
64
  end
34
65
  end
35
66
  end
@@ -1,38 +1,19 @@
1
1
  require 'cheffish'
2
- require 'chef/resource/lwrp_base'
2
+ require 'cheffish/base_resource'
3
3
  require 'chef/run_list/run_list_item'
4
+ require 'chef/chef_fs/data_handler/role_data_handler'
4
5
 
5
6
  class Chef
6
7
  class Resource
7
- class ChefRole < Chef::Resource::LWRPBase
8
- self.resource_name = 'chef_role'
8
+ class ChefRole < Cheffish::BaseResource
9
+ resource_name :chef_role
9
10
 
10
- actions :create, :delete, :nothing
11
- default_action :create
12
-
13
- # Grab environment from with_environment
14
- def initialize(*args)
15
- super
16
- chef_server run_context.cheffish.current_chef_server
17
- end
18
-
19
- attribute :name, :kind_of => String, :regex => Cheffish::NAME_REGEX, :name_attribute => true
20
- attribute :description, :kind_of => String
21
- attribute :run_list, :kind_of => Array # We should let them specify it as a series of parameters too
22
- attribute :env_run_lists, :kind_of => Hash
23
- attribute :default_attributes, :kind_of => Hash
24
- attribute :override_attributes, :kind_of => Hash
25
-
26
- # Specifies that this is a complete specification for the environment (i.e. attributes you don't specify will be
27
- # reset to their defaults)
28
- attribute :complete, :kind_of => [TrueClass, FalseClass]
29
-
30
- attribute :raw_json, :kind_of => Hash
31
- attribute :chef_server, :kind_of => Hash
32
-
33
- # `NOT_PASSED` is defined in chef-12.5.0, this guard will ensure we
34
- # don't redefine it if it's already there
35
- NOT_PASSED=Object.new unless defined?(NOT_PASSED)
11
+ property :name, Cheffish::NAME_REGEX, name_property: true
12
+ property :description, String
13
+ property :run_list, Array # We should let them specify it as a series of parameters too
14
+ property :env_run_lists, Hash
15
+ property :default_attributes, Hash
16
+ property :override_attributes, Hash
36
17
 
37
18
  # default_attribute 'ip_address', '127.0.0.1'
38
19
  # default_attribute [ 'pushy', 'port' ], '9000'
@@ -105,6 +86,77 @@ class Chef
105
86
  @run_list_removers ||= []
106
87
  @run_list_removers += roles.map { |recipe| Chef::RunList::RunListItem.new("role[#{role}]") }
107
88
  end
89
+
90
+ action :create do
91
+ differences = json_differences(current_json, new_json)
92
+
93
+ if current_resource_exists?
94
+ if differences.size > 0
95
+ description = [ "update role #{new_resource.name} at #{rest.url}" ] + differences
96
+ converge_by description do
97
+ rest.put("roles/#{new_resource.name}", normalize_for_put(new_json))
98
+ end
99
+ end
100
+ else
101
+ description = [ "create role #{new_resource.name} at #{rest.url}" ] + differences
102
+ converge_by description do
103
+ rest.post("roles", normalize_for_post(new_json))
104
+ end
105
+ end
106
+ end
107
+
108
+ action :delete do
109
+ if current_resource_exists?
110
+ converge_by "delete role #{new_resource.name} at #{rest.url}" do
111
+ rest.delete("roles/#{new_resource.name}")
112
+ end
113
+ end
114
+ end
115
+
116
+ action_class.class_eval do
117
+ def load_current_resource
118
+ begin
119
+ @current_resource = json_to_resource(rest.get("roles/#{new_resource.name}"))
120
+ rescue Net::HTTPServerException => e
121
+ if e.response.code == "404"
122
+ @current_resource = not_found_resource
123
+ else
124
+ raise
125
+ end
126
+ end
127
+ end
128
+
129
+ def augment_new_json(json)
130
+ # Apply modifiers
131
+ json['run_list'] = apply_run_list_modifiers(new_resource.run_list_modifiers, new_resource.run_list_removers, json['run_list'])
132
+ json['default_attributes'] = apply_modifiers(new_resource.default_attribute_modifiers, json['default_attributes'])
133
+ json['override_attributes'] = apply_modifiers(new_resource.override_attribute_modifiers, json['override_attributes'])
134
+ json
135
+ end
136
+
137
+ #
138
+ # Helpers
139
+ #
140
+
141
+ def resource_class
142
+ Chef::Resource::ChefRole
143
+ end
144
+
145
+ def data_handler
146
+ Chef::ChefFS::DataHandler::RoleDataHandler.new
147
+ end
148
+
149
+ def keys
150
+ {
151
+ 'name' => :name,
152
+ 'description' => :description,
153
+ 'run_list' => :run_list,
154
+ 'env_run_lists' => :env_run_lists,
155
+ 'default_attributes' => :default_attributes,
156
+ 'override_attributes' => :override_attributes
157
+ }
158
+ end
159
+ end
108
160
  end
109
161
  end
110
162
  end
@@ -1,46 +1,31 @@
1
1
  require 'cheffish'
2
- require 'chef/resource/lwrp_base'
2
+ require 'cheffish/chef_actor_base'
3
3
 
4
4
  class Chef
5
5
  class Resource
6
- class ChefUser < Chef::Resource::LWRPBase
7
- self.resource_name = 'chef_user'
8
-
9
- actions :create, :delete, :nothing
10
- default_action :create
11
-
12
- # Grab environment from with_environment
13
- def initialize(*args)
14
- super
15
- chef_server run_context.cheffish.current_chef_server
16
- end
6
+ class ChefUser < Cheffish::ChefActorBase
7
+ resource_name :chef_user
17
8
 
18
9
  # Client attributes
19
- attribute :name, :kind_of => String, :regex => Cheffish::NAME_REGEX, :name_attribute => true
20
- attribute :display_name, :kind_of => String
21
- attribute :admin, :kind_of => [TrueClass, FalseClass]
22
- attribute :email, :kind_of => String
23
- attribute :external_authentication_uid
24
- attribute :recovery_authentication_enabled, :kind_of => [TrueClass, FalseClass]
25
- attribute :password, :kind_of => String # Hmm. There is no way to idempotentize this.
26
- #attribute :salt # TODO server doesn't support sending or receiving these, but it's the only way to backup / restore a user
27
- #attribute :hashed_password
28
- #attribute :hash_type
10
+ property :name, Cheffish::NAME_REGEX, name_property: true
11
+ property :display_name, String
12
+ property :admin, Boolean
13
+ property :email, String
14
+ property :external_authentication_uid
15
+ property :recovery_authentication_enabled, Boolean
16
+ property :password, String # Hmm. There is no way to idempotentize this.
17
+ #property :salt # TODO server doesn't support sending or receiving these, but it's the only way to backup / restore a user
18
+ #property :hashed_password
19
+ #property :hash_type
29
20
 
30
21
  # Input key
31
- attribute :source_key # String or OpenSSL::PKey::*
32
- attribute :source_key_path, :kind_of => String
33
- attribute :source_key_pass_phrase
22
+ property :source_key # String or OpenSSL::PKey::*
23
+ property :source_key_path, String
24
+ property :source_key_pass_phrase
34
25
 
35
26
  # Output public key (if so desired)
36
- attribute :output_key_path, :kind_of => String
37
- attribute :output_key_format, :kind_of => Symbol, :default => :openssh, :equal_to => [ :pem, :der, :openssh ]
38
-
39
- # If this is set, client is not patchy
40
- attribute :complete, :kind_of => [TrueClass, FalseClass]
41
-
42
- attribute :raw_json, :kind_of => Hash
43
- attribute :chef_server, :kind_of => Hash
27
+ property :output_key_path, String
28
+ property :output_key_format, [ :pem, :der, :openssh ], default: :openssh
44
29
 
45
30
  # Proc that runs just before the resource executes. Called with (resource)
46
31
  def before(&block)
@@ -51,6 +36,52 @@ class Chef
51
36
  def after(&block)
52
37
  block ? @after = block : @after
53
38
  end
39
+
40
+
41
+ action :create do
42
+ create_actor
43
+ end
44
+
45
+ action :delete do
46
+ delete_actor
47
+ end
48
+
49
+ action_class.class_eval do
50
+ #
51
+ # Helpers
52
+ #
53
+ # Gives us new_json, current_json, not_found_json, etc.
54
+
55
+ def actor_type
56
+ 'user'
57
+ end
58
+
59
+ def actor_path
60
+ "#{rest.root_url}/users"
61
+ end
62
+
63
+ def resource_class
64
+ Chef::Resource::ChefUser
65
+ end
66
+
67
+ def data_handler
68
+ Chef::ChefFS::DataHandler::UserDataHandler.new
69
+ end
70
+
71
+ def keys
72
+ {
73
+ 'name' => :name,
74
+ 'username' => :name,
75
+ 'display_name' => :display_name,
76
+ 'admin' => :admin,
77
+ 'email' => :email,
78
+ 'password' => :password,
79
+ 'external_authentication_uid' => :external_authentication_uid,
80
+ 'recovery_authentication_enabled' => :recovery_authentication_enabled,
81
+ 'public_key' => :source_key
82
+ }
83
+ end
84
+ end
54
85
  end
55
86
  end
56
87
  end
@@ -1,38 +1,40 @@
1
1
  require 'openssl/cipher'
2
- require 'chef/resource/lwrp_base'
2
+ require 'cheffish/base_resource'
3
+ require 'openssl'
4
+ require 'cheffish/key_formatter'
3
5
 
4
6
  class Chef
5
7
  class Resource
6
- class PrivateKey < Chef::Resource::LWRPBase
7
- self.resource_name = 'private_key'
8
+ class PrivateKey < Cheffish::BaseResource
9
+ resource_name :private_key
8
10
 
9
- actions :create, :delete, :regenerate, :nothing
11
+ allowed_actions :create, :delete, :regenerate, :nothing
10
12
  default_action :create
11
13
 
12
14
  # Path to private key. Set to :none to create the key in memory and not on disk.
13
- attribute :path, :kind_of => [ String, Symbol ], :name_attribute => true
14
- attribute :format, :kind_of => Symbol, :default => :pem, :equal_to => [ :pem, :der ]
15
- attribute :type, :kind_of => Symbol, :default => :rsa, :equal_to => [ :rsa, :dsa ] # TODO support :ec
15
+ property :path, [ String, :none ], name_property: true
16
+ property :format, [ :pem, :der ], default: :pem
17
+ property :type, [ :rsa, :dsa ], default: :rsa # TODO support :ec
16
18
  # These specify an optional public_key you can spit out if you want.
17
- attribute :public_key_path, :kind_of => String
18
- attribute :public_key_format, :kind_of => Symbol, :default => :openssh, :equal_to => [ :openssh, :pem, :der ]
19
+ property :public_key_path, String
20
+ property :public_key_format, [ :openssh, :pem, :der ], default: :openssh
19
21
  # Specify this if you want to copy another private key but give it a different format / password
20
- attribute :source_key
21
- attribute :source_key_path, :kind_of => String
22
- attribute :source_key_pass_phrase
22
+ property :source_key
23
+ property :source_key_path, String
24
+ property :source_key_pass_phrase
23
25
 
24
26
  # RSA and DSA
25
- attribute :size, :kind_of => Integer, :default => 2048
27
+ property :size, Integer, default: 2048
26
28
 
27
29
  # RSA-only
28
- attribute :exponent, :kind_of => Integer # For RSA
30
+ property :exponent, Integer # For RSA
29
31
 
30
32
  # PEM-only
31
- attribute :pass_phrase, :kind_of => String
32
- attribute :cipher, :kind_of => String, :default => 'DES-EDE3-CBC', :equal_to => OpenSSL::Cipher.ciphers
33
+ property :pass_phrase, String
34
+ property :cipher, OpenSSL::Cipher.ciphers, default: 'DES-EDE3-CBC'
33
35
 
34
36
  # Set this to regenerate the key if it does not have the desired characteristics (like size, type, etc.)
35
- attribute :regenerate_if_different, :kind_of => [TrueClass, FalseClass]
37
+ property :regenerate_if_different, Boolean
36
38
 
37
39
  # Proc that runs after the resource completes. Called with (resource, private_key)
38
40
  def after(&block)
@@ -43,6 +45,217 @@ class Chef
43
45
  def load_prior_resource(*args)
44
46
  Chef::Log.debug("Overloading #{resource_name}.load_prior_resource with NOOP")
45
47
  end
48
+
49
+
50
+ action :create do
51
+ create_key(false, :create)
52
+ end
53
+
54
+ action :regenerate do
55
+ create_key(true, :regenerate)
56
+ end
57
+
58
+ action :delete do
59
+ if current_resource.path
60
+ converge_by "delete private key #{new_path}" do
61
+ ::File.unlink(new_path)
62
+ end
63
+ end
64
+ end
65
+
66
+ action_class.class_eval do
67
+ def create_key(regenerate, action)
68
+ if @should_create_directory
69
+ Cheffish.inline_resource(self, action) do
70
+ directory run_context.config[:private_key_write_path]
71
+ end
72
+ end
73
+
74
+ final_private_key = nil
75
+ if new_source_key
76
+ #
77
+ # Create private key from source
78
+ #
79
+ desired_output = encode_private_key(new_source_key)
80
+ if current_resource.path == :none || desired_output != IO.read(new_path)
81
+ converge_by "reformat key at #{new_resource.source_key_path} to #{new_resource.format} private key #{new_path} (#{new_resource.pass_phrase ? ", #{new_resource.cipher} password" : ""})" do
82
+ IO.write(new_path, desired_output)
83
+ end
84
+ end
85
+
86
+ final_private_key = new_source_key
87
+
88
+ else
89
+ #
90
+ # Generate a new key
91
+ #
92
+ if current_resource.action == [ :delete ] || regenerate ||
93
+ (new_resource.regenerate_if_different &&
94
+ (!current_private_key ||
95
+ current_resource.size != new_resource.size ||
96
+ current_resource.type != new_resource.type))
97
+
98
+ case new_resource.type
99
+ when :rsa
100
+ if new_resource.exponent
101
+ final_private_key = OpenSSL::PKey::RSA.generate(new_resource.size, new_resource.exponent)
102
+ else
103
+ final_private_key = OpenSSL::PKey::RSA.generate(new_resource.size)
104
+ end
105
+ when :dsa
106
+ final_private_key = OpenSSL::PKey::DSA.generate(new_resource.size)
107
+ end
108
+
109
+ generated_key = true
110
+ elsif !current_private_key
111
+ raise "Could not read private key from #{current_resource.path}: missing pass phrase?"
112
+ else
113
+ final_private_key = current_private_key
114
+ generated_key = false
115
+ end
116
+
117
+ if generated_key
118
+ generated_description = " (#{new_resource.size} bits#{new_resource.pass_phrase ? ", #{new_resource.cipher} password" : ""})"
119
+
120
+ if new_path != :none
121
+ action = current_resource.path == :none ? 'create' : 'overwrite'
122
+ converge_by "#{action} #{new_resource.type} private key #{new_path}#{generated_description}" do
123
+ write_private_key(final_private_key)
124
+ end
125
+ else
126
+ converge_by "generate private key#{generated_description}" do
127
+ end
128
+ end
129
+ else
130
+ # Warn if existing key has different characteristics than expected
131
+ if current_resource.size != new_resource.size
132
+ Chef::Log.warn("Mismatched key size! #{current_resource.path} is #{current_resource.size} bytes, desired is #{new_resource.size} bytes. Use action :regenerate to force key regeneration.")
133
+ elsif current_resource.type != new_resource.type
134
+ Chef::Log.warn("Mismatched key type! #{current_resource.path} is #{current_resource.type}, desired is #{new_resource.type} bytes. Use action :regenerate to force key regeneration.")
135
+ end
136
+
137
+ if current_resource.format != new_resource.format
138
+ converge_by "change format of #{new_resource.type} private key #{new_path} from #{current_resource.format} to #{new_resource.format}" do
139
+ write_private_key(current_private_key)
140
+ end
141
+ elsif (@current_file_mode & 0077) != 0
142
+ new_mode = @current_file_mode & 07700
143
+ converge_by "change mode of private key #{new_path} to #{new_mode.to_s(8)}" do
144
+ ::File.chmod(new_mode, new_path)
145
+ end
146
+ end
147
+ end
148
+ end
149
+
150
+ if new_resource.public_key_path
151
+ public_key_path = new_resource.public_key_path
152
+ public_key_format = new_resource.public_key_format
153
+ Cheffish.inline_resource(self, action) do
154
+ public_key public_key_path do
155
+ source_key final_private_key
156
+ format public_key_format
157
+ end
158
+ end
159
+ end
160
+
161
+ if new_resource.after
162
+ new_resource.after.call(new_resource, final_private_key)
163
+ end
164
+ end
165
+
166
+ def encode_private_key(key)
167
+ key_format = {}
168
+ key_format[:format] = new_resource.format if new_resource.format
169
+ key_format[:pass_phrase] = new_resource.pass_phrase if new_resource.pass_phrase
170
+ key_format[:cipher] = new_resource.cipher if new_resource.cipher
171
+ Cheffish::KeyFormatter.encode(key, key_format)
172
+ end
173
+
174
+ def write_private_key(key)
175
+ ::File.open(new_path, 'w') do |file|
176
+ file.chmod(0600)
177
+ file.write(encode_private_key(key))
178
+ end
179
+ end
180
+
181
+ def new_source_key
182
+ @new_source_key ||= begin
183
+ if new_resource.source_key.is_a?(String)
184
+ source_key, source_key_format = Cheffish::KeyFormatter.decode(new_resource.source_key, new_resource.source_key_pass_phrase)
185
+ source_key
186
+ elsif new_resource.source_key
187
+ new_resource.source_key
188
+ elsif new_resource.source_key_path
189
+ source_key, source_key_format = Cheffish::KeyFormatter.decode(IO.read(new_resource.source_key_path), new_resource.source_key_pass_phrase, new_resource.source_key_path)
190
+ source_key
191
+ else
192
+ nil
193
+ end
194
+ end
195
+ end
196
+
197
+ attr_reader :current_private_key
198
+
199
+ def new_path
200
+ new_key_with_path[1]
201
+ end
202
+
203
+ def new_key_with_path
204
+ path = new_resource.path
205
+ if path.is_a?(Symbol)
206
+ return [ nil, path ]
207
+ elsif Pathname.new(path).relative?
208
+ private_key, private_key_path = Cheffish.get_private_key_with_path(path, run_context.config)
209
+ if private_key
210
+ return [ private_key, (private_key_path || :none) ]
211
+ elsif run_context.config[:private_key_write_path]
212
+ @should_create_directory = true
213
+ path = ::File.join(run_context.config[:private_key_write_path], path)
214
+ return [ nil, path ]
215
+ else
216
+ raise "Could not find key #{path} and Chef::Config.private_key_write_path is not set."
217
+ end
218
+ elsif ::File.exist?(path)
219
+ return [ IO.read(path), path ]
220
+ else
221
+ return [ nil, path ]
222
+ end
223
+ end
224
+
225
+ def load_current_resource
226
+ resource = Chef::Resource::PrivateKey.new(new_resource.name, run_context)
227
+
228
+ new_key, new_path = new_key_with_path
229
+ if new_path != :none && ::File.exist?(new_path)
230
+ resource.path new_path
231
+ @current_file_mode = ::File.stat(new_path).mode
232
+ else
233
+ resource.path :none
234
+ end
235
+
236
+ if new_key
237
+ begin
238
+ key, key_format = Cheffish::KeyFormatter.decode(new_key, new_resource.pass_phrase, new_path)
239
+ if key
240
+ @current_private_key = key
241
+ resource.format key_format[:format]
242
+ resource.type key_format[:type]
243
+ resource.size key_format[:size]
244
+ resource.exponent key_format[:exponent]
245
+ resource.pass_phrase key_format[:pass_phrase]
246
+ resource.cipher key_format[:cipher]
247
+ end
248
+ rescue
249
+ # If there's an error reading, we assume format and type are wrong and don't futz with them
250
+ Chef::Log.warn("Error reading #{new_path}: #{$!}")
251
+ end
252
+ else
253
+ resource.action :delete
254
+ end
255
+
256
+ @current_resource = resource
257
+ end
258
+ end
46
259
  end
47
260
  end
48
261
  end