diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..ae18fce --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,2 @@ +AllCops: + TargetRubyVersion: 2.6 \ No newline at end of file diff --git a/Rakefile b/Rakefile index 3a9ba3a..179f296 100644 --- a/Rakefile +++ b/Rakefile @@ -39,4 +39,4 @@ task :console do IRB.start end -task default: [:style, :spec] +task default: %i{style spec} diff --git a/lib/chef/resource/chef_acl.rb b/lib/chef/resource/chef_acl.rb index bdda348..7a2dd10 100644 --- a/lib/chef/resource/chef_acl.rb +++ b/lib/chef/resource/chef_acl.rb @@ -99,6 +99,7 @@ def create_acl(path) # NOTE: if superusers exist, this should turn into a warning. raise "chef_acl attempted to remove all actors from GRANT! I'm sorry Dave, I can't let you remove access to an object with no hope of recovery." end + modify[differences] ||= {} modify[differences][permission] = desired_json end @@ -107,7 +108,7 @@ def create_acl(path) if modify.size > 0 changed = true description = [ "update acl #{path} at #{rest_url(path)}" ] + modify.flat_map do |diffs, permissions| - diffs.map { |diff| " #{permissions.keys.join(', ')}:#{diff}" } + diffs.map { |diff| " #{permissions.keys.join(", ")}:#{diff}" } end converge_by description do modify.values.each do |permissions| @@ -127,11 +128,13 @@ def create_acl(path) children, _error = list(path, "*") Chef::ChefFS::Parallelizer.parallel_do(children) do |child| next if child.split("/")[-1] == "containers" + create_acl(child) end # containers mess up our descent, so we do them last Chef::ChefFS::Parallelizer.parallel_do(children) do |child| next if child.split("/")[-1] != "containers" + create_acl(child) end @@ -141,7 +144,7 @@ def create_acl(path) # Get the current ACL for the given path def current_acl(acl_path) @current_acls ||= {} - if !@current_acls.key?(acl_path) + unless @current_acls.key?(acl_path) @current_acls[acl_path] = begin rest.get(rest_url(acl_path)) rescue Net::HTTPServerException => e @@ -252,8 +255,7 @@ def remove_rights(json) end end - def load_current_resource - end + def load_current_resource; end # # Matches chef_acl paths like nodes, nodes/*. @@ -270,7 +272,7 @@ def load_current_resource def match_paths(path) # Turn multiple slashes into one # nodes//x -> nodes/x - path = path.gsub(/[\/]+/, "/") + path = path.gsub(%r{[/]+}, "/") # If it's absolute, start the matching with /. If it's relative, start with '' (relative root). if path[0] == "/" matches = [ "/" ] @@ -305,6 +307,7 @@ def match_paths(path) if parts[0..index - 1].all? { |p| p != "*" } raise error end + [] else found @@ -421,21 +424,21 @@ def list(path, child) when 1 # /organizations/*, /users/*, roles/*, nodes/*, etc. results, error = rest_list(path) - if !error + unless error results = results.map { |result| ::File.join(path, result) } end when 2 # /organizations/NAME/* results, error = rest_list(::File.join(path, "containers")) - if !error + unless error results = results.map { |result| ::File.join(path, result) } end when 3 # /organizations/NAME/TYPE/* results, error = rest_list(path) - if !error + unless error results = results.map { |result| ::File.join(path, result) } end end diff --git a/lib/chef/resource/chef_client.rb b/lib/chef/resource/chef_client.rb index 78ada46..21871b8 100644 --- a/lib/chef/resource/chef_client.rb +++ b/lib/chef/resource/chef_client.rb @@ -18,7 +18,7 @@ class ChefClient < Cheffish::ChefActorBase # Output public key (if so desired) property :output_key_path, String - property :output_key_format, Symbol, default: :openssh, equal_to: [ :pem, :der, :openssh ] + property :output_key_format, Symbol, default: :openssh, equal_to: %i{pem der openssh} # Proc that runs just before the resource executes. Called with (resource) def before(&block) diff --git a/lib/chef/resource/chef_container.rb b/lib/chef/resource/chef_container.rb index c2de5f4..d529f8c 100644 --- a/lib/chef/resource/chef_container.rb +++ b/lib/chef/resource/chef_container.rb @@ -10,7 +10,7 @@ class ChefContainer < Cheffish::BaseResource property :chef_container_name, Cheffish::NAME_REGEX, name_property: true action :create do - if !@current_exists + unless @current_exists converge_by "create container #{new_resource.chef_container_name} at #{rest.url}" do rest.post("containers", normalize_for_post(new_json)) end diff --git a/lib/chef/resource/chef_data_bag.rb b/lib/chef/resource/chef_data_bag.rb index 72875a5..1eba9aa 100644 --- a/lib/chef/resource/chef_data_bag.rb +++ b/lib/chef/resource/chef_data_bag.rb @@ -9,7 +9,7 @@ class ChefDataBag < Cheffish::BaseResource property :data_bag_name, Cheffish::NAME_REGEX, name_property: true action :create do - if !current_resource_exists? + unless current_resource_exists? converge_by "create data bag #{new_resource.data_bag_name} at #{rest.url}" do rest.post("data", { "name" => new_resource.data_bag_name }) end diff --git a/lib/chef/resource/chef_data_bag_item.rb b/lib/chef/resource/chef_data_bag_item.rb index a3a2181..0fe4c8f 100644 --- a/lib/chef/resource/chef_data_bag_item.rb +++ b/lib/chef/resource/chef_data_bag_item.rb @@ -137,7 +137,7 @@ def load_current_resource # If the current secret doesn't work, look through the specified old secrets - if !current_resource.secret + unless current_resource.secret old_secrets = [] if new_resource.old_secret old_secrets += Array(new_resource.old_secret) @@ -148,17 +148,17 @@ def load_current_resource end end old_secrets.each do |secret| - begin - Chef::EncryptedDataBagItem::Decryptor.for(first_real_value, secret).for_decrypted_item - current_resource.secret secret - rescue Chef::EncryptedDataBagItem::DecryptionFailure - decrypt_error = $! - end + + Chef::EncryptedDataBagItem::Decryptor.for(first_real_value, secret).for_decrypted_item + current_resource.secret secret + rescue Chef::EncryptedDataBagItem::DecryptionFailure + decrypt_error = $! + end # If we couldn't figure out the secret, emit a warning (this isn't a fatal flaw unless we # need to reuse one of the values from the data bag) - if !current_resource.secret + unless current_resource.secret if decrypt_error Chef::Log.warn "Existing data bag is encrypted, but could not decrypt: #{decrypt_error.message}." else @@ -280,9 +280,10 @@ def calculate_differences elsif current_resource.encrypt # Encryption is different and we can't read the old values. Only allow the change # if we're overwriting the data bag item - if !new_resource.complete + unless new_resource.complete raise "Cannot encrypt #{new_resource.name} due to failure to decrypt existing resource. Set 'complete true' to overwrite or add the old secret as old_secret / old_secret_path." end + _differences = [ "overwrite data bag item (cannot decrypt old data bag item)"] differences = (new_resource.raw_data.keys & current_resource.raw_data.keys).map { |key| "overwrite #{key}" } differences += (new_resource.raw_data.keys - current_resource.raw_data.keys).map { |key| "add #{key}" } diff --git a/lib/chef/resource/chef_mirror.rb b/lib/chef/resource/chef_mirror.rb index 02c48bf..4fb8e89 100644 --- a/lib/chef/resource/chef_mirror.rb +++ b/lib/chef/resource/chef_mirror.rb @@ -95,6 +95,7 @@ def copy_to(src_root, dest_root) if new_resource.concurrency <= 0 raise "chef_mirror.concurrency must be above 0! Was set to #{new_resource.concurrency}" end + # Honor concurrency Chef::ChefFS::Parallelizer.threads = new_resource.concurrency - 1 @@ -103,13 +104,14 @@ def copy_to(src_root, dest_root) if new_resource.path[0] == "/" raise "Absolute paths in chef_mirror not yet supported." end + # Copy! path = Chef::ChefFS::FilePattern.new("/#{new_resource.path}") ui = CopyListener.new(self) error = Chef::ChefFS::FileSystem.copy_to(path, src_root, dest_root, nil, options, ui, proc { |p| p.path }) if error - raise "Errors while copying:#{ui.errors.map { |e| "#{e}\n" }.join('')}" + raise "Errors while copying:#{ui.errors.map { |e| "#{e}\n" }.join("")}" end end @@ -163,7 +165,7 @@ def remote_fs end def repo_mode - new_resource.chef_server[:chef_server_url] =~ /\/organizations\// ? "hosted_everything" : "everything" + new_resource.chef_server[:chef_server_url] =~ %r{/organizations/} ? "hosted_everything" : "everything" end def options @@ -179,8 +181,7 @@ def options result end - def load_current_resource - end + def load_current_resource; end class CopyListener def initialize(mirror) diff --git a/lib/chef/resource/chef_organization.rb b/lib/chef/resource/chef_organization.rb index cc2d405..3447c43 100644 --- a/lib/chef/resource/chef_organization.rb +++ b/lib/chef/resource/chef_organization.rb @@ -68,7 +68,7 @@ class ChefOrganization < Cheffish::BaseResource end end new_resource.members.each do |user| - if !existing_members.include?(user) + unless existing_members.include?(user) converge_by "Add #{user} to organization #{new_resource.organization_name}" do rest.post("#{rest.root_url}/organizations/#{new_resource.organization_name}/users/", { "username" => user }) end diff --git a/lib/chef/resource/chef_resolved_cookbooks.rb b/lib/chef/resource/chef_resolved_cookbooks.rb index 74a6b48..25a4568 100644 --- a/lib/chef/resource/chef_resolved_cookbooks.rb +++ b/lib/chef/resource/chef_resolved_cookbooks.rb @@ -43,7 +43,8 @@ def cookbooks_from(path = nil) new_resource.berksfile.upload( server_url: new_resource.chef_server[:chef_server_url], client_name: new_resource.chef_server[:options][:client_name], - client_key: new_resource.chef_server[:options][:signing_key_filename]) + client_key: new_resource.chef_server[:options][:signing_key_filename] + ) else file = Tempfile.new("privatekey") begin @@ -53,7 +54,8 @@ def cookbooks_from(path = nil) new_resource.berksfile.upload( server_url: new_resource.chef_server[:chef_server_url], client_name: new_resource.chef_server[:options][:client_name] || "me", - client_key: file.path) + client_key: file.path + ) ensure file.close diff --git a/lib/chef/resource/chef_role.rb b/lib/chef/resource/chef_role.rb index 20c2751..e20c5e4 100644 --- a/lib/chef/resource/chef_role.rb +++ b/lib/chef/resource/chef_role.rb @@ -62,6 +62,7 @@ def recipe(*recipes) if recipes.size == 0 raise ArgumentError, "At least one recipe must be specified" end + @run_list_modifiers ||= [] @run_list_modifiers += recipes.map { |recipe| Chef::RunList::RunListItem.new("recipe[#{recipe}]") } end @@ -70,6 +71,7 @@ def role(*roles) if roles.size == 0 raise ArgumentError, "At least one role must be specified" end + @run_list_modifiers ||= [] @run_list_modifiers += roles.map { |role| Chef::RunList::RunListItem.new("role[#{role}]") } end @@ -78,6 +80,7 @@ def remove_recipe(*recipes) if recipes.size == 0 raise ArgumentError, "At least one recipe must be specified" end + @run_list_removers ||= [] @run_list_removers += recipes.map { |recipe| Chef::RunList::RunListItem.new("recipe[#{recipe}]") } end @@ -86,6 +89,7 @@ def remove_role(*roles) if roles.size == 0 raise ArgumentError, "At least one role must be specified" end + @run_list_removers ||= [] @run_list_removers += roles.map { |recipe| Chef::RunList::RunListItem.new("role[#{role}]") } end diff --git a/lib/chef/resource/chef_user.rb b/lib/chef/resource/chef_user.rb index 0a8f594..7e088b5 100644 --- a/lib/chef/resource/chef_user.rb +++ b/lib/chef/resource/chef_user.rb @@ -25,7 +25,7 @@ class ChefUser < Cheffish::ChefActorBase # Output public key (if so desired) property :output_key_path, String - property :output_key_format, [ :pem, :der, :openssh ], default: :openssh + property :output_key_format, %i{pem der openssh}, default: :openssh # Proc that runs just before the resource executes. Called with (resource) def before(&block) diff --git a/lib/chef/resource/private_key.rb b/lib/chef/resource/private_key.rb index 664bfab..8161d17 100644 --- a/lib/chef/resource/private_key.rb +++ b/lib/chef/resource/private_key.rb @@ -13,11 +13,11 @@ class PrivateKey < Cheffish::BaseResource # Path to private key. Set to :none to create the key in memory and not on disk. property :path, [ String, :none ], name_property: true - property :format, [ :pem, :der ], default: :pem - property :type, [ :rsa, :dsa ], default: :rsa # TODO support :ec + property :format, %i{pem der}, default: :pem + property :type, %i{rsa dsa}, default: :rsa # TODO support :ec # These specify an optional public_key you can spit out if you want. property :public_key_path, String - property :public_key_format, [ :openssh, :pem, :der ], default: :openssh + property :public_key_format, %i{openssh pem der}, default: :openssh # Specify this if you want to copy another private key but give it a different format / password property :source_key property :source_key_path, String @@ -31,7 +31,7 @@ class PrivateKey < Cheffish::BaseResource # PEM-only property :pass_phrase, String - property :cipher, String, equal_to: OpenSSL::Cipher.ciphers.map { |x| x.downcase }, default: "des-ede3-cbc", coerce: proc { |x| x.downcase } + property :cipher, String, equal_to: OpenSSL::Cipher.ciphers.map(&:downcase), default: "des-ede3-cbc", coerce: proc { |x| x.downcase } # Set this to regenerate the key if it does not have the desired characteristics (like size, type, etc.) property :regenerate_if_different, [TrueClass, FalseClass] diff --git a/lib/chef/resource/public_key.rb b/lib/chef/resource/public_key.rb index cc612c0..e21a656 100644 --- a/lib/chef/resource/public_key.rb +++ b/lib/chef/resource/public_key.rb @@ -12,7 +12,7 @@ class PublicKey < Cheffish::BaseResource default_action :create property :path, String, name_property: true - property :format, [ :pem, :der, :openssh ], default: :openssh + property :format, %i{pem der openssh}, default: :openssh property :source_key property :source_key_path, String @@ -24,9 +24,10 @@ def load_prior_resource(*args) end action :create do - if !new_source_key + unless new_source_key raise "No source key specified" end + desired_output = encode_public_key(new_source_key) if Array(current_resource.action) == [ :delete ] || desired_output != IO.read(new_resource.path) converge_by "write #{new_resource.format} public key #{new_resource.path} from #{new_source_key_publicity} key #{new_resource.source_key_path}" do diff --git a/lib/cheffish.rb b/lib/cheffish.rb index 88bcfc1..164e86f 100644 --- a/lib/cheffish.rb +++ b/lib/cheffish.rb @@ -98,6 +98,7 @@ def self.get_private_key_with_path(name, config = profiled_config) elsif config[:private_key_paths] config[:private_key_paths].each do |private_key_path| next unless File.exist?(private_key_path) + Dir.entries(private_key_path).sort.each do |key| ext = File.extname(key) if key == name || ext == "" || ext == ".pem" diff --git a/lib/cheffish/base_resource.rb b/lib/cheffish/base_resource.rb index 5fc0664..acb7e19 100644 --- a/lib/cheffish/base_resource.rb +++ b/lib/cheffish/base_resource.rb @@ -91,7 +91,7 @@ def json_differences(old_json, new_json, print_values = true, name = "", result end def json_differences_internal(old_json, new_json, print_values, name, result) - if old_json.kind_of?(Hash) && new_json.kind_of?(Hash) + if old_json.is_a?(Hash) && new_json.is_a?(Hash) removed_keys = old_json.keys.inject({}) { |hash, key| hash[key] = true; hash } new_json.each_pair do |new_key, new_value| if old_json.key?(new_key) @@ -101,18 +101,18 @@ def json_differences_internal(old_json, new_json, print_values, name, result) end else if print_values - result << " add #{name == '' ? new_key : "#{name}.#{new_key}"} = #{new_value.inspect}" + result << " add #{name == "" ? new_key : "#{name}.#{new_key}"} = #{new_value.inspect}" else - result << " add #{name == '' ? new_key : "#{name}.#{new_key}"}" + result << " add #{name == "" ? new_key : "#{name}.#{new_key}"}" end end end removed_keys.keys.each do |removed_key| - result << " remove #{name == '' ? removed_key : "#{name}.#{removed_key}"}" + result << " remove #{name == "" ? removed_key : "#{name}.#{removed_key}"}" end else - old_json = old_json.to_s if old_json.kind_of?(Symbol) - new_json = new_json.to_s if new_json.kind_of?(Symbol) + old_json = old_json.to_s if old_json.is_a?(Symbol) + new_json = new_json.to_s if new_json.is_a?(Symbol) if old_json != new_json if print_values result << " update #{name} from #{old_json.inspect} to #{new_json.inspect}" @@ -134,8 +134,8 @@ def apply_modifiers(modifiers, json) end modifiers.each do |path, value| - path = [path] if !path.kind_of?(Array) - path = path.map { |path_part| path_part.to_s } + path = [path] unless path.is_a?(Array) + path = path.map(&:to_s) parent = 0.upto(path.size - 2).inject(json) do |hash, index| if hash.nil? nil @@ -148,6 +148,7 @@ def apply_modifiers(modifiers, json) if !parent.nil? && !parent.is_a?(Hash) raise "Attempt to set #{path} to #{value} when #{path[0..-2]} is not a hash" end + existing_value = parent ? parent[path[-1]] : nil if value.is_a?(Proc) @@ -158,7 +159,7 @@ def apply_modifiers(modifiers, json) else # Create parent if necessary, overwriting values parent = path[0..-2].inject(json) do |hash, path_part| - hash[path_part] = {} if !hash[path_part] + hash[path_part] = {} unless hash[path_part] hash[path_part] end if path.size > 0 @@ -173,6 +174,7 @@ def apply_modifiers(modifiers, json) def apply_run_list_modifiers(add_to_run_list, delete_from_run_list, run_list) return run_list if (!add_to_run_list || add_to_run_list.size == 0) && (!delete_from_run_list || !delete_from_run_list.size) + delete_from_run_list ||= [] add_to_run_list ||= [] @@ -191,7 +193,7 @@ def apply_run_list_modifiers(add_to_run_list, delete_from_run_list, run_list) # because found_desired will be less than add_to_run_list_index. The result will # be X, A, B, Y, Z. if found_desired >= add_to_run_list_index - result += add_to_run_list[add_to_run_list_index..found_desired].map { |item| item.to_s } + result += add_to_run_list[add_to_run_list_index..found_desired].map(&:to_s) add_to_run_list_index = found_desired + 1 end else @@ -204,7 +206,7 @@ def apply_run_list_modifiers(add_to_run_list, delete_from_run_list, run_list) end # Copy any remaining desired items at the end - result += add_to_run_list[add_to_run_list_index..-1].map { |item| item.to_s } + result += add_to_run_list[add_to_run_list_index..-1].map(&:to_s) result end diff --git a/lib/cheffish/basic_chef_client.rb b/lib/cheffish/basic_chef_client.rb index 64cbb08..5f960f5 100644 --- a/lib/cheffish/basic_chef_client.rb +++ b/lib/cheffish/basic_chef_client.rb @@ -14,7 +14,7 @@ class BasicChefClient include Chef::DSL::Recipe def initialize(node = nil, events = nil, **chef_config) - if !node + unless node node = Chef::Node.new node.name "basic_chef_client" node.automatic[:platform] = "basic_chef_client" @@ -31,7 +31,7 @@ def initialize(node = nil, events = nil, **chef_config) case events when Array events.each { |e| dispatcher.register(e) } if events - when !nil + when !nil # rubocop: disable Lint/LiteralAsCondition dispatcher.register(events) end @run_context = Chef::RunContext.new(node, {}, dispatcher) diff --git a/lib/cheffish/chef_actor_base.rb b/lib/cheffish/chef_actor_base.rb index 056320a..f1c26c2 100644 --- a/lib/cheffish/chef_actor_base.rb +++ b/lib/cheffish/chef_actor_base.rb @@ -24,9 +24,10 @@ def create_actor end else # Create the actor if it's missing - if !new_public_key + unless new_public_key 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." end + description = [ "create #{actor_type} #{new_resource.name} at #{actor_path}" ] + differences converge_by description do result = rest.post((actor_path).to_s, normalize_for_post(new_json)) diff --git a/lib/cheffish/chef_run.rb b/lib/cheffish/chef_run.rb index 5a46a03..0760734 100644 --- a/lib/cheffish/chef_run.rb +++ b/lib/cheffish/chef_run.rb @@ -34,15 +34,14 @@ def write(*args, &block) def client @client ||= begin chef_config = self.chef_config.dup - chef_config[:log_level] ||= :debug if !chef_config.key?(:log_level) - chef_config[:verbose_logging] = false if !chef_config.key?(:verbose_logging) + chef_config[:log_level] ||= :debug unless chef_config.key?(:log_level) + chef_config[:verbose_logging] = false unless chef_config.key?(:verbose_logging) chef_config[:stdout] = StringIOTee.new(chef_config[:stdout]) chef_config[:stderr] = StringIOTee.new(chef_config[:stderr]) chef_config[:log_location] = StringIOTee.new(chef_config[:log_location]) @client = ::Cheffish::BasicChefClient.new(nil, [ event_sink, Chef::Formatters.new(:doc, chef_config[:stdout], chef_config[:stderr]) ], - chef_config - ) + chef_config) end end @@ -125,14 +124,14 @@ def output_for_failure_message message << "--- Chef Client Output ---\n" message << "--- ---\n" message << stdout - message << "\n" if !stdout.end_with?("\n") + message << "\n" unless stdout.end_with?("\n") end if stderr && !stderr.empty? message << "--- ---\n" message << "--- Chef Client Error Output ---\n" message << "--- ---\n" message << stderr - message << "\n" if !stderr.end_with?("\n") + message << "\n" unless stderr.end_with?("\n") end if logs && !logs.empty? message << "--- ---\n" diff --git a/lib/cheffish/chef_run_listener.rb b/lib/cheffish/chef_run_listener.rb index 26179f9..c93611a 100644 --- a/lib/cheffish/chef_run_listener.rb +++ b/lib/cheffish/chef_run_listener.rb @@ -21,9 +21,7 @@ def run_failed(exception) def disconnect # Stop the servers if node.run_context - node.run_context.cheffish.local_servers.each do |server| - server.stop - end + node.run_context.cheffish.local_servers.each(&:stop) end end end diff --git a/lib/cheffish/key_formatter.rb b/lib/cheffish/key_formatter.rb index efa1fba..40bf31e 100644 --- a/lib/cheffish/key_formatter.rb +++ b/lib/cheffish/key_formatter.rb @@ -58,6 +58,7 @@ def self.encode(key, key_format) if RUBY_VERSION.to_f >= 2.0 raise "PKCS8 SHA1 not supported in Ruby #{RUBY_VERSION}" end + require "openssl_pkcs8" pkcs8_pem = key.to_pem_pkcs8 pkcs8_base64 = pkcs8_pem.split("\n").reject { |l| l =~ /^-----/ } diff --git a/lib/cheffish/merged_config.rb b/lib/cheffish/merged_config.rb index 84c33c7..2d3cbd7 100644 --- a/lib/cheffish/merged_config.rb +++ b/lib/cheffish/merged_config.rb @@ -27,7 +27,7 @@ def [](name) result_configs = [] configs.each do |config| value = config[name] - if !value.nil? + unless value.nil? if value.respond_to?(:keys) result_configs << value elsif result_configs.size > 0 @@ -63,7 +63,7 @@ def key?(name) alias_method :has_key?, :key? def keys - configs.flat_map { |c| c.keys }.uniq + configs.flat_map(&:keys).uniq end def values diff --git a/lib/cheffish/node_properties.rb b/lib/cheffish/node_properties.rb index f9666c5..ed55ee5 100644 --- a/lib/cheffish/node_properties.rb +++ b/lib/cheffish/node_properties.rb @@ -39,7 +39,7 @@ def tag(*tags) attribute "tags" do |existing_tags| existing_tags ||= [] tags.each do |tag| - if !existing_tags.include?(tag.to_s) + unless existing_tags.include?(tag.to_s) existing_tags << tag.to_s end end @@ -64,8 +64,8 @@ def tags(*tags) if tags.size == 0 attribute("tags") else - tags = tags[0] if tags.size == 1 && tags[0].kind_of?(Array) - attribute("tags", tags.map { |tag| tag.to_s }) + tags = tags[0] if tags.size == 1 && tags[0].is_a?(Array) + attribute("tags", tags.map(&:to_s)) end end @@ -80,6 +80,7 @@ def recipe(*recipes) if recipes.size == 0 raise ArgumentError, "At least one recipe must be specified" end + @run_list_modifiers ||= [] @run_list_modifiers += recipes.map { |recipe| Chef::RunList::RunListItem.new("recipe[#{recipe}]") } end @@ -88,6 +89,7 @@ def role(*roles) if roles.size == 0 raise ArgumentError, "At least one role must be specified" end + @run_list_modifiers ||= [] @run_list_modifiers += roles.map { |role| Chef::RunList::RunListItem.new("role[#{role}]") } end @@ -96,6 +98,7 @@ def remove_recipe(*recipes) if recipes.size == 0 raise ArgumentError, "At least one recipe must be specified" end + @run_list_removers ||= [] @run_list_removers += recipes.map { |recipe| Chef::RunList::RunListItem.new("recipe[#{recipe}]") } end @@ -104,6 +107,7 @@ def remove_role(*roles) if roles.size == 0 raise ArgumentError, "At least one role must be specified" end + @run_list_removers ||= [] @run_list_removers += roles.map { |role| Chef::RunList::RunListItem.new("role[#{role}]") } end diff --git a/lib/cheffish/recipe_dsl.rb b/lib/cheffish/recipe_dsl.rb index 5d2a323..2331f84 100644 --- a/lib/cheffish/recipe_dsl.rb +++ b/lib/cheffish/recipe_dsl.rb @@ -52,7 +52,7 @@ def with_chef_local_server(options, &block) # Create the data store chef-zero will use options[:data_store] ||= begin - if !options[:chef_repo_path] + unless options[:chef_repo_path] raise "chef_repo_path must be specified to with_chef_local_server" end @@ -63,7 +63,7 @@ def with_chef_local_server(options, &block) symbol_key = "#{type}_path".to_sym options[symbol_key] ||= begin - if options[:chef_repo_path].kind_of?(String) + if options[:chef_repo_path].is_a?(String) Chef::Util::PathHelper.join(options[:chef_repo_path], "#{type}s") else options[:chef_repo_path].map { |path| Chef::Util::PathHelper.join(path, "#{type}s") } diff --git a/lib/cheffish/rspec/chef_run_support.rb b/lib/cheffish/rspec/chef_run_support.rb index 16a7ad1..96e5518 100644 --- a/lib/cheffish/rspec/chef_run_support.rb +++ b/lib/cheffish/rspec/chef_run_support.rb @@ -58,7 +58,7 @@ def expect_converge(str = nil, file = nil, line = nil, &recipe) end def recipe(str = nil, file = nil, line = nil, &recipe) - if !recipe + unless recipe if file && line recipe = proc { eval(str, nil, file, line) } # rubocop:disable Security/Eval else diff --git a/lib/cheffish/rspec/matchers/have_updated.rb b/lib/cheffish/rspec/matchers/have_updated.rb index b00c8a9..8987ddd 100644 --- a/lib/cheffish/rspec/matchers/have_updated.rb +++ b/lib/cheffish/rspec/matchers/have_updated.rb @@ -5,16 +5,16 @@ @recipe = recipe actual = @recipe.event_sink.events actual_actions = actual.select { |event, resource, action| event == :resource_updated && resource.to_s == resource_name } - .map { |event, resource, action| action } + .map { |event, resource, action| action } expect(actual_actions).to eq(expected_actions) end failure_message do actual = @recipe.event_sink.events updates = actual.select { |event, resource, action| event == :resource_updated }.to_a - result = "expected that the chef_run would #{expected_actions.join(',')} #{resource_name}." + result = "expected that the chef_run would #{expected_actions.join(",")} #{resource_name}." if updates.size > 0 - result << " Actual updates were #{updates.map { |event, resource, action| "#{resource} => #{action.inspect}" }.join(', ')}" + result << " Actual updates were #{updates.map { |event, resource, action| "#{resource} => #{action.inspect}" }.join(", ")}" else result << " Nothing was updated." end @@ -24,9 +24,9 @@ failure_message_when_negated do actual = @recipe.event_sink.events updates = actual.select { |event, resource, action| event == :resource_updated }.to_a - result = "expected that the chef_run would not #{expected_actions.join(',')} #{resource_name}." + result = "expected that the chef_run would not #{expected_actions.join(",")} #{resource_name}." if updates.size > 0 - result << " Actual updates were #{updates.map { |event, resource, action| "#{resource} => #{action.inspect}" }.join(', ')}" + result << " Actual updates were #{updates.map { |event, resource, action| "#{resource} => #{action.inspect}" }.join(", ")}" else result << " Nothing was updated." end diff --git a/lib/cheffish/rspec/recipe_run_wrapper.rb b/lib/cheffish/rspec/recipe_run_wrapper.rb index 5bcc043..ac03606 100644 --- a/lib/cheffish/rspec/recipe_run_wrapper.rb +++ b/lib/cheffish/rspec/recipe_run_wrapper.rb @@ -14,7 +14,7 @@ def initialize(chef_config, example: nil, &recipe) attr_reader :example def client - if !@client + unless @client super example = self.example diff --git a/lib/cheffish/rspec/repository_support.rb b/lib/cheffish/rspec/repository_support.rb index b405144..1ab0e1f 100644 --- a/lib/cheffish/rspec/repository_support.rb +++ b/lib/cheffish/rspec/repository_support.rb @@ -12,6 +12,7 @@ def when_the_repository(desc, *tags, &block) ::RSpec.shared_context "with a chef repo" do before :each do raise "Can only create one directory per test" if @repository_dir + @repository_dir = Dir.mktmpdir("chef_repo") Chef::Config.chef_repo_path = @repository_dir %w{client cookbook data_bag environment node role user}.each do |object_name| diff --git a/spec/functional/fingerprint_spec.rb b/spec/functional/fingerprint_spec.rb index 53f75ef..20dd523 100644 --- a/spec/functional/fingerprint_spec.rb +++ b/spec/functional/fingerprint_spec.rb @@ -41,22 +41,26 @@ def key_to_format(key, format) it "computes the PKCS#8 SHA1 private key fingerprint correctly", pending: (RUBY_VERSION.to_f >= 2.0) do expect(key_to_format(sample_private_key, :pkcs8sha1fingerprint)).to eq( - "88:7e:3a:bd:26:9f:b5:c5:d8:ae:52:f9:df:0b:64:a4:5c:17:0a:87") + "88:7e:3a:bd:26:9f:b5:c5:d8:ae:52:f9:df:0b:64:a4:5c:17:0a:87" + ) end it "computes the PKCS#1 MD5 public key fingerprint correctly" do expect(key_to_format(sample_public_key, :pkcs1md5fingerprint)).to eq( - "1f:e8:da:c1:16:c3:72:7d:90:e2:b7:64:c4:b4:55:20") + "1f:e8:da:c1:16:c3:72:7d:90:e2:b7:64:c4:b4:55:20" + ) end it "computes the RFC4716 MD5 public key fingerprint correctly" do expect(key_to_format(sample_public_key, :rfc4716md5fingerprint)).to eq( - "b0:13:4f:da:cf:8c:dc:a7:4a:1f:d2:3a:51:92:cf:6b") + "b0:13:4f:da:cf:8c:dc:a7:4a:1f:d2:3a:51:92:cf:6b" + ) end it "defaults to the PKCS#1 MD5 public key fingerprint" do expect(key_to_format(sample_public_key, :fingerprint)).to eq( - key_to_format(sample_public_key, :pkcs1md5fingerprint)) + key_to_format(sample_public_key, :pkcs1md5fingerprint) + ) end end diff --git a/spec/integration/chef_acl_spec.rb b/spec/integration/chef_acl_spec.rb index 07aeab5..cebd1aa 100644 --- a/spec/integration/chef_acl_spec.rb +++ b/spec/integration/chef_acl_spec.rb @@ -160,7 +160,7 @@ it 'Converging chef_acl "nodes/x" with rights [ :read, :create, :update, :delete, :grant ] modifies all rights' do expect_recipe do chef_acl "nodes/x" do - rights [ :create, :read, :update, :delete, :grant ], users: %w{u1 u2}, clients: %w{c1}, groups: %w{g1} + rights %i{create read update delete grant}, users: %w{u1 u2}, clients: %w{c1}, groups: %w{g1} end end.to be_updated expect(get("nodes/x/_acl")).to partially_match( @@ -229,11 +229,11 @@ end end.to be_updated expect(get("nodes/x/_acl")).to partially_match( - "create" => { "actors" => exclude("foo") }, - "read" => { "actors" => exclude("foo") }, - "update" => { "actors" => exclude("foo") }, - "delete" => { "actors" => exclude("foo") }, - "grant" => { "actors" => exclude("foo") } + "create" => { "actors" => exclude("foo") }, + "read" => { "actors" => exclude("foo") }, + "update" => { "actors" => exclude("foo") }, + "delete" => { "actors" => exclude("foo") }, + "grant" => { "actors" => exclude("foo") } ) end end @@ -361,7 +361,8 @@ end.to be_updated %w{clients containers cookbooks data environments groups nodes roles}.each do |type| expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match( - "read" => { "actors" => %w{u} }) + "read" => { "actors" => %w{u} } + ) end end end @@ -408,7 +409,8 @@ end.to be_updated %w{clients containers cookbooks data environments groups nodes roles sandboxes}.each do |type| expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match( - "read" => { "actors" => %w{u} }) + "read" => { "actors" => %w{u} } + ) end end @@ -420,7 +422,8 @@ end.to be_updated %w{clients containers cookbooks data environments groups nodes roles}.each do |type| expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match( - "read" => { "actors" => %w{u} }) + "read" => { "actors" => %w{u} } + ) end end @@ -447,7 +450,7 @@ chef_acl "/organizations/foo/cookbooks/x/1.0.0" do rights :read, users: %w{u} end - end.to raise_error(/ACLs cannot be set on children of \/organizations\/foo\/cookbooks\/x/) + end.to raise_error(%r{ACLs cannot be set on children of /organizations/foo/cookbooks/x}) end it "chef_acl '/organizations/foo/cookbooks/*/*' raises an error" do @@ -456,7 +459,7 @@ chef_acl "/organizations/foo/cookbooks/*/*" do rights :read, users: %w{u} end - end.to raise_error(/ACLs cannot be set on children of \/organizations\/foo\/cookbooks\/*/) + end.to raise_error(%r{ACLs cannot be set on children of /organizations/foo/cookbooks/*}) end it 'chef_acl "/organizations/foo/data/x/y" raises an error' do @@ -464,7 +467,7 @@ chef_acl "/organizations/foo/data/x/y" do rights :read, users: %w{u} end - end.to raise_error(/ACLs cannot be set on children of \/organizations\/foo\/data\/x/) + end.to raise_error(%r{ACLs cannot be set on children of /organizations/foo/data/x}) end it 'chef_acl "/organizations/foo/data/*/*" raises an error' do @@ -473,7 +476,7 @@ chef_acl "/organizations/foo/data/*/*" do rights :read, users: %w{u} end - end.to raise_error(/ACLs cannot be set on children of \/organizations\/foo\/data\/*/) + end.to raise_error(%r{ACLs cannot be set on children of /organizations/foo/data/*}) end it 'chef_acl "/organizations/foo" changes the acl' do @@ -609,7 +612,8 @@ end.to be_updated %w{clients containers cookbooks data environments groups nodes roles sandboxes}.each do |type| expect(get("#{type}/x/_acl")).to partially_match( - "read" => { "actors" => %w{u} }) + "read" => { "actors" => %w{u} } + ) end end @@ -621,7 +625,8 @@ end.to be_updated %w{clients containers cookbooks data environments groups nodes roles}.each do |type| expect(get("#{type}/x/_acl")).to partially_match( - "read" => { "actors" => %w{u} }) + "read" => { "actors" => %w{u} } + ) end end @@ -633,7 +638,8 @@ end.to be_updated %w{admins billing-admins clients users x}.each do |n| expect(get("groups/#{n}/_acl")).to partially_match( - "read" => { "actors" => %w{u} }) + "read" => { "actors" => %w{u} } + ) end end @@ -713,7 +719,8 @@ end.to be_updated %w{clients containers cookbooks data environments groups nodes roles sandboxes}.each do |type| expect(get("/organizations/foo/containers/#{type}/_acl")).to partially_match( - "read" => { "actors" => %w{u} }) + "read" => { "actors" => %w{u} } + ) end end @@ -768,7 +775,8 @@ end.to be_updated %w{clients containers cookbooks data environments groups nodes roles sandboxes}.each do |type| expect(get("containers/#{type}/_acl")).to partially_match( - "read" => { "actors" => %w{u} }) + "read" => { "actors" => %w{u} } + ) end end end @@ -820,7 +828,7 @@ it 'chef_acl with remove_rights [ :create, :read ], "u", "c", "g" removes all three' do expect_recipe do chef_acl "nodes/x" do - remove_rights [ :create, :read ], users: %w{u}, clients: %w{c}, groups: %w{g} + remove_rights %i{create read}, users: %w{u}, clients: %w{c}, groups: %w{g} end end.to be_updated expect(get("nodes/x/_acl")).to partially_match(