cheffish 1.6.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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