end
action :add do
- current_resource = @current_resource
filename = @current_resource.filename
keyname = @current_resource.keyname
- caps = @new_resource.caps.map { |k, v| "#{k} '#{v}'" }.join(' ')
+ as_keyring = @current_resource.as_keyring
owner = @new_resource.owner
group = @new_resource.group
mode = @new_resource.mode
- unless @current_resource.caps_match
- converge_by("Set caps for #{@new_resource}") do
- auth_set_key(keyname, caps)
- current_resource.key = get_key(keyname)
+ if @current_resource.exists
+ if @current_resource.keys_match && @current_resource.caps_match
+ Chef::Log.info "Client #{ @new_resource } already exists and matches "\
+ 'specifications - nothing to do.'
+ else
+ converge_by("Recreating client #{ @new_resource } as existing doesn't "\
+ 'match specifications') do
+ delete_entity(keyname)
+ create_entity(keyname)
+ end
+ end
+ else
+ converge_by("Creating client #{ @new_resource }") do
+ create_entity(keyname)
end
end
+
+ # Obtain the randomly generated key if one wasn't provided
+ key = @new_resource.key || get_key(keyname)
+
# update the key in the file
file filename do
- content file_content
+ content file_content(keyname, key, as_keyring)
owner owner
group group
mode mode
+ # sensitive true if Chef::Resource::File.method_defined? :sensitive # ~FC009
end
end
@current_resource = Chef::Resource::CephClient.new(@new_resource.name)
@current_resource.name(@new_resource.name)
@current_resource.as_keyring(@new_resource.as_keyring)
- @current_resource.keyname(@new_resource.keyname || "client.#{current_resource.name}.#{node['hostname']}")
+ @current_resource.keyname(@new_resource.keyname || "client.#{@new_resource.name}.#{node['hostname']}")
@current_resource.caps(get_caps(@current_resource.keyname))
default_filename = "/etc/ceph/ceph.client.#{@new_resource.name}.#{node['hostname']}.#{@new_resource.as_keyring ? 'keyring' : 'secret'}"
@current_resource.filename(@new_resource.filename || default_filename)
- @current_resource.key = get_key(@current_resource.keyname)
- @current_resource.caps_match = true if @current_resource.caps == @new_resource.caps
+ @current_resource.key(get_key(@current_resource.keyname))
+ @current_resource.caps_match = @current_resource.caps == @new_resource.caps
+ @current_resource.keys_match = @new_resource.key.nil? || (@current_resource.key == @new_resource.key)
+ @current_resource.exists = ! (@current_resource.key.nil? || @current_resource.key.empty?)
end
-def file_content
- @current_resource.as_keyring ? "[#{@current_resource.keyname}]\n\tkey = #{@current_resource.key}\n" : @current_resource.key
+def file_content(keyname, key, as_keyring)
+ if as_keyring
+ "[#{keyname}]\n\tkey = #{key}\n"
+ else
+ key
+ end
end
def get_key(keyname)
caps
end
-def auth_set_key(keyname, caps)
- secret = mon_secret
- # try to add the key
- cmd = "ceph auth get-or-create #{keyname} #{caps} --name mon. --key='#{secret}'"
- get_or_create = Mixlib::ShellOut.new(cmd)
- get_or_create.run_command
- if get_or_create.stderr.scan(/EINVAL.*but cap.*does not match/)
- Chef::Log.info('Deleting old key with incorrect caps')
- # delete an old key if it exists and is wrong
- Mixlib::ShellOut.new("ceph auth del #{keyname} --name mon. --key='#{secret}'").run_command
- # try to create again
- get_or_create = Mixlib::ShellOut.new(cmd)
- get_or_create.run_command
+def delete_entity(keyname)
+ cmd_text = "ceph auth del #{keyname} --name mon. --key='#{mon_secret}'"
+ cmd = Mixlib::ShellOut.new(cmd_text)
+ cmd.run_command
+ cmd.error!
+ Chef::Log.debug "Client #{keyname} deleted"
+end
+
+def create_entity(keyname)
+ tmp_keyring = "#{Chef::Config[:file_cache_path]}/.#{keyname}.keyring"
+
+ if new_resource.key
+ # store key provided in a temporary keyring file
+ cmd_text = "ceph-authtool #{tmp_keyring} --create-keyring --name #{keyname} "\
+ "--add-key '#{new_resource.key}'"
+ cmd = Mixlib::ShellOut.new(cmd_text)
+ cmd.run_command
+ cmd.error!
+
+ key_option = "-i #{tmp_keyring}"
+ else
+ key_option = ''
+ end
+
+ caps = new_resource.caps.map { |k, v| "#{k} '#{v}'" }.join(' ')
+
+ cmd_text = "ceph auth #{key_option} add #{keyname} #{caps} --name mon. "\
+ "--key='#{mon_secret}'"
+ cmd = Mixlib::ShellOut.new(cmd_text)
+ cmd.run_command
+ cmd.error!
+ Chef::Log.debug "Client #{keyname} created"
+
+ # remove temporary keyring file
+ file tmp_keyring do
+ action :delete
+ # sensitive true if Chef::Resource::File.method_defined? :sensitive # ~FC009
end
- get_or_create.error!
end
# defaults to client.#{name}.#{hostname}
attribute :keyname, :kind_of => String
+# The actual key (a random key will be generated if not provided)
+attribute :key, :kind_of => String, :default => nil
+
# where the key should be saved
# defaults to /etc/ceph/ceph.client.#{name}.#{hostname}.keyring if as_keyring
# defaults to /etc/ceph/ceph.client.#{name}.#{hostname}.secret if not as_keyring
attribute :group, :kind_of => String, :default => 'root'
attribute :mode, :kind_of => [Integer, String], :default => '00640'
-attr_accessor :key, :caps_match
+attr_accessor :exists, :caps_match, :keys_match