cheffish 4.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +8 -8
  3. data/Rakefile +24 -12
  4. data/cheffish.gemspec +15 -15
  5. data/lib/chef/resource/chef_acl.rb +63 -63
  6. data/lib/chef/resource/chef_client.rb +9 -9
  7. data/lib/chef/resource/chef_container.rb +9 -9
  8. data/lib/chef/resource/chef_data_bag.rb +9 -9
  9. data/lib/chef/resource/chef_data_bag_item.rb +27 -27
  10. data/lib/chef/resource/chef_environment.rb +21 -22
  11. data/lib/chef/resource/chef_group.rb +19 -19
  12. data/lib/chef/resource/chef_mirror.rb +32 -17
  13. data/lib/chef/resource/chef_node.rb +14 -14
  14. data/lib/chef/resource/chef_organization.rb +29 -30
  15. data/lib/chef/resource/chef_resolved_cookbooks.rb +7 -7
  16. data/lib/chef/resource/chef_role.rb +25 -22
  17. data/lib/chef/resource/chef_user.rb +13 -14
  18. data/lib/chef/resource/private_key.rb +24 -25
  19. data/lib/chef/resource/public_key.rb +6 -7
  20. data/lib/cheffish.rb +17 -17
  21. data/lib/cheffish/array_property.rb +2 -2
  22. data/lib/cheffish/base_properties.rb +3 -3
  23. data/lib/cheffish/base_resource.rb +8 -8
  24. data/lib/cheffish/basic_chef_client.rb +17 -17
  25. data/lib/cheffish/chef_actor_base.rb +8 -8
  26. data/lib/cheffish/chef_run.rb +7 -2
  27. data/lib/cheffish/chef_run_data.rb +2 -2
  28. data/lib/cheffish/chef_run_listener.rb +1 -1
  29. data/lib/cheffish/key_formatter.rb +16 -18
  30. data/lib/cheffish/merged_config.rb +5 -3
  31. data/lib/cheffish/node_properties.rb +11 -7
  32. data/lib/cheffish/recipe_dsl.rb +33 -34
  33. data/lib/cheffish/rspec.rb +3 -3
  34. data/lib/cheffish/rspec/chef_run_support.rb +13 -13
  35. data/lib/cheffish/rspec/matchers.rb +4 -4
  36. data/lib/cheffish/rspec/matchers/be_idempotent.rb +3 -3
  37. data/lib/cheffish/rspec/matchers/emit_no_warnings_or_errors.rb +3 -3
  38. data/lib/cheffish/rspec/matchers/have_updated.rb +3 -3
  39. data/lib/cheffish/rspec/recipe_run_wrapper.rb +8 -7
  40. data/lib/cheffish/rspec/repository_support.rb +6 -6
  41. data/lib/cheffish/server_api.rb +11 -11
  42. data/lib/cheffish/version.rb +1 -1
  43. data/spec/functional/fingerprint_spec.rb +12 -12
  44. data/spec/functional/merged_config_spec.rb +46 -6
  45. data/spec/functional/server_api_spec.rb +3 -3
  46. data/spec/integration/chef_acl_spec.rb +489 -489
  47. data/spec/integration/chef_client_spec.rb +39 -39
  48. data/spec/integration/chef_container_spec.rb +14 -14
  49. data/spec/integration/chef_data_bag_item_spec.rb +9 -9
  50. data/spec/integration/chef_group_spec.rb +219 -219
  51. data/spec/integration/chef_mirror_spec.rb +228 -228
  52. data/spec/integration/chef_node_spec.rb +511 -511
  53. data/spec/integration/chef_organization_spec.rb +126 -126
  54. data/spec/integration/chef_role_spec.rb +33 -33
  55. data/spec/integration/chef_user_spec.rb +37 -37
  56. data/spec/integration/private_key_spec.rb +154 -154
  57. data/spec/integration/recipe_dsl_spec.rb +10 -10
  58. data/spec/integration/rspec/converge_spec.rb +49 -49
  59. data/spec/support/key_support.rb +6 -6
  60. data/spec/support/spec_support.rb +3 -3
  61. data/spec/unit/get_private_key_spec.rb +19 -19
  62. data/spec/unit/recipe_run_wrapper_spec.rb +4 -4
  63. metadata +3 -3
@@ -1,7 +1,7 @@
1
- require 'openssl/cipher'
2
- require 'cheffish/base_resource'
3
- require 'openssl'
4
- require 'cheffish/key_formatter'
1
+ require "openssl/cipher"
2
+ require "cheffish/base_resource"
3
+ require "openssl"
4
+ require "cheffish/key_formatter"
5
5
 
6
6
  class Chef
7
7
  class Resource
@@ -23,7 +23,6 @@ class Chef
23
23
  Chef::Log.debug("Overloading #{resource_name}.load_prior_resource with NOOP")
24
24
  end
25
25
 
26
-
27
26
  action :create do
28
27
  if !new_source_key
29
28
  raise "No source key specified"
@@ -68,10 +67,10 @@ class Chef
68
67
  end
69
68
 
70
69
  if source_key.private?
71
- @new_source_key_publicity = 'private'
70
+ @new_source_key_publicity = "private"
72
71
  source_key.public_key
73
72
  else
74
- @new_source_key_publicity = 'public'
73
+ @new_source_key_publicity = "public"
75
74
  source_key
76
75
  end
77
76
  end
data/lib/cheffish.rb CHANGED
@@ -10,8 +10,8 @@ module Cheffish
10
10
  :chef_server_url => config[:chef_server_url],
11
11
  :options => {
12
12
  :client_name => config[:node_name],
13
- :signing_key_filename => config[:client_key]
14
- }
13
+ :signing_key_filename => config[:client_key],
14
+ },
15
15
  }
16
16
  end
17
17
 
@@ -19,7 +19,7 @@ module Cheffish
19
19
  # Pin the server api version to 0 until https://github.com/chef/cheffish/issues/56
20
20
  # gets the correct compatibility fix.
21
21
  chef_server[:options] ||= {}
22
- chef_server[:options].merge!(api_version: "0")
22
+ chef_server[:options][:api_version] = "0"
23
23
  Cheffish::ServerAPI.new(chef_server[:chef_server_url], chef_server[:options])
24
24
  end
25
25
 
@@ -32,7 +32,7 @@ module Cheffish
32
32
  end
33
33
 
34
34
  def self.load_chef_config(chef_config = Chef::Config)
35
- if ::Gem::Version.new(::Chef::VERSION) >= ::Gem::Version.new('12.0.0')
35
+ if ::Gem::Version.new(::Chef::VERSION) >= ::Gem::Version.new("12.0.0")
36
36
  chef_config.config_file = ::Chef::Knife.chef_config_dir
37
37
  else
38
38
  chef_config.config_file = ::Chef::Knife.locate_config_file
@@ -50,7 +50,7 @@ module Cheffish
50
50
  rescue Exception => error
51
51
  Chef::Log.fatal("Configuration error #{error.class}: #{error.message}")
52
52
  filtered_trace = error.backtrace.grep(/#{Regexp.escape(config_file_path)}/)
53
- filtered_trace.each {|line| Chef::Log.fatal(" " + line )}
53
+ filtered_trace.each { |line| Chef::Log.fatal(" " + line ) }
54
54
  Chef::Application.fatal!("Aborting due to error in '#{config_file_path}'", 2)
55
55
  end
56
56
  end
@@ -65,7 +65,7 @@ module Cheffish
65
65
  Chef::Config.chef_repo_path = Chef::Config.find_chef_repo_path(Dir.pwd)
66
66
  end
67
67
  begin
68
- require 'chef/local_mode'
68
+ require "chef/local_mode"
69
69
  Chef::LocalMode.with_server_connectivity(&block)
70
70
 
71
71
  rescue LoadError
@@ -100,8 +100,8 @@ module Cheffish
100
100
  next unless File.exist?(private_key_path)
101
101
  Dir.entries(private_key_path).sort.each do |key|
102
102
  ext = File.extname(key)
103
- if key == name || ext == '' || ext == '.pem'
104
- key_name = key[0..-(ext.length+1)]
103
+ if key == name || ext == "" || ext == ".pem"
104
+ key_name = key[0..-(ext.length + 1)]
105
105
  if key_name == name || key == name
106
106
  Chef::Log.info("Reading key #{name} from file #{private_key_path}/#{key}")
107
107
  return [ IO.read("#{private_key_path}/#{key}"), "#{private_key_path}/#{key}" ]
@@ -120,12 +120,12 @@ end
120
120
 
121
121
  # Include all recipe objects so require 'cheffish' brings in the whole recipe DSL
122
122
 
123
- require 'chef/run_list/run_list_item'
124
- require 'cheffish/basic_chef_client'
125
- require 'cheffish/server_api'
126
- require 'chef/knife'
127
- require 'chef/config_fetcher'
128
- require 'chef/log'
129
- require 'chef/application'
130
- require 'cheffish/recipe_dsl'
131
- require 'cheffish/node_properties'
123
+ require "chef/run_list/run_list_item"
124
+ require "cheffish/basic_chef_client"
125
+ require "cheffish/server_api"
126
+ require "chef/knife"
127
+ require "chef/config_fetcher"
128
+ require "chef/log"
129
+ require "chef/application"
130
+ require "cheffish/recipe_dsl"
131
+ require "cheffish/node_properties"
@@ -1,4 +1,4 @@
1
- require 'chef/property'
1
+ require "chef/property"
2
2
 
3
3
  module Cheffish
4
4
  # A typical array property. Defaults to [], accepts multiple args to setter, accumulates values.
@@ -12,7 +12,7 @@ module Cheffish
12
12
 
13
13
  # Support my_property 'a', 'b', 'c'; my_property 'a'; and my_property ['a', 'b']
14
14
  def emit_dsl
15
- declared_in.class_eval(<<-EOM, __FILE__, __LINE__+1)
15
+ declared_in.class_eval(<<-EOM, __FILE__, __LINE__ + 1)
16
16
  def #{name}(*values)
17
17
  property = self.class.properties[#{name.inspect}]
18
18
  if values.empty?
@@ -1,6 +1,6 @@
1
- require 'chef/mixin/properties'
2
- require 'cheffish/array_property'
3
- require 'cheffish'
1
+ require "chef/mixin/properties"
2
+ require "cheffish/array_property"
3
+ require "cheffish"
4
4
 
5
5
  module Cheffish
6
6
  module BaseProperties
@@ -1,5 +1,5 @@
1
- require 'chef/resource'
2
- require 'cheffish/base_properties'
1
+ require "chef/resource"
2
+ require "cheffish/base_properties"
3
3
 
4
4
  module Cheffish
5
5
  class BaseResource < Chef::Resource
@@ -84,7 +84,7 @@ module Cheffish
84
84
  data_handler.normalize(json, fake_entry)
85
85
  end
86
86
 
87
- def json_differences(old_json, new_json, print_values=true, name = '', result = nil)
87
+ def json_differences(old_json, new_json, print_values = true, name = "", result = nil)
88
88
  result ||= []
89
89
  json_differences_internal(old_json, new_json, print_values, name, result)
90
90
  result
@@ -97,7 +97,7 @@ module Cheffish
97
97
  if old_json.has_key?(new_key)
98
98
  removed_keys.delete(new_key)
99
99
  if new_value != old_json[new_key]
100
- json_differences_internal(old_json[new_key], new_value, print_values, name == '' ? new_key : "#{name}.#{new_key}", result)
100
+ json_differences_internal(old_json[new_key], new_value, print_values, name == "" ? new_key : "#{name}.#{new_key}", result)
101
101
  end
102
102
  else
103
103
  if print_values
@@ -136,11 +136,11 @@ module Cheffish
136
136
  modifiers.each do |path, value|
137
137
  path = [path] if !path.kind_of?(Array)
138
138
  path = path.map { |path_part| path_part.to_s }
139
- parent = 0.upto(path.size-2).inject(json) do |hash, index|
139
+ parent = 0.upto(path.size - 2).inject(json) do |hash, index|
140
140
  if hash.nil?
141
141
  nil
142
142
  elsif !hash.is_a?(Hash)
143
- raise "Attempt to set #{path} to #{value} when #{path[0..index-1]} is not a hash"
143
+ raise "Attempt to set #{path} to #{value} when #{path[0..index - 1]} is not a hash"
144
144
  else
145
145
  hash[path[index]]
146
146
  end
@@ -181,7 +181,7 @@ module Cheffish
181
181
  result = []
182
182
  add_to_run_list_index = 0
183
183
  run_list_index = 0
184
- while run_list_index < run_list.run_list_items.size do
184
+ while run_list_index < run_list.run_list_items.size
185
185
  # See if the desired run list has this item
186
186
  found_desired = add_to_run_list.index { |item| same_run_list_item(item, run_list[run_list_index]) }
187
187
  if found_desired
@@ -192,7 +192,7 @@ module Cheffish
192
192
  # be X, A, B, Y, Z.
193
193
  if found_desired >= add_to_run_list_index
194
194
  result += add_to_run_list[add_to_run_list_index..found_desired].map { |item| item.to_s }
195
- add_to_run_list_index = found_desired+1
195
+ add_to_run_list_index = found_desired + 1
196
196
  end
197
197
  else
198
198
  # If not, just copy it in
@@ -1,13 +1,13 @@
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'
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
11
 
12
12
  module Cheffish
13
13
  class BasicChefClient
@@ -16,8 +16,8 @@ module Cheffish
16
16
  def initialize(node = nil, events = nil, **chef_config)
17
17
  if !node
18
18
  node = Chef::Node.new
19
- node.name 'basic_chef_client'
20
- node.automatic[:platform] = 'basic_chef_client'
19
+ node.name "basic_chef_client"
20
+ node.automatic[:platform] = "basic_chef_client"
21
21
  node.automatic[:platform_version] = Cheffish::VERSION
22
22
  end
23
23
 
@@ -25,7 +25,7 @@ module Cheffish
25
25
  @chef_config = chef_config
26
26
 
27
27
  with_chef_config do
28
- @cookbook_name = 'basic_chef_client'
28
+ @cookbook_name = "basic_chef_client"
29
29
  @event_catcher = BasicChefClientEvents.new
30
30
  dispatcher = Chef::EventDispatch::Dispatcher.new(@event_catcher)
31
31
  case events
@@ -37,7 +37,7 @@ module Cheffish
37
37
  end
38
38
  @run_context = Chef::RunContext.new(node, {}, dispatcher)
39
39
  @updated = []
40
- @cookbook_name = 'basic_chef_client'
40
+ @cookbook_name = "basic_chef_client"
41
41
  end
42
42
  end
43
43
 
@@ -58,7 +58,7 @@ module Cheffish
58
58
 
59
59
  def load_block(&block)
60
60
  with_chef_config do
61
- @recipe_name = 'block'
61
+ @recipe_name = "block"
62
62
  instance_eval(&block)
63
63
  end
64
64
  end
@@ -79,7 +79,7 @@ module Cheffish
79
79
 
80
80
  # Builds a resource sans context, which can be later used in a new client's
81
81
  # add_resource() method.
82
- def self.build_resource(type, name, created_at=nil, &resource_attrs_block)
82
+ def self.build_resource(type, name, created_at = nil, &resource_attrs_block)
83
83
  created_at ||= caller[0]
84
84
  result = BasicChefClient.new.tap do |client|
85
85
  client.with_chef_config do
@@ -129,7 +129,7 @@ module Cheffish
129
129
  # end
130
130
  begin
131
131
  deep_merge_config(chef_config, Chef::Config)
132
- block.call
132
+ yield
133
133
  ensure
134
134
  # $stdout = old_stdout if chef_config[:stdout]
135
135
  # $stderr = old_stderr if chef_config[:stderr]
@@ -1,5 +1,5 @@
1
- require 'cheffish/key_formatter'
2
- require 'cheffish/base_resource'
1
+ require "cheffish/key_formatter"
2
+ require "cheffish/base_resource"
3
3
 
4
4
  module Cheffish
5
5
  class ChefActorBase < Cheffish::BaseResource
@@ -11,7 +11,7 @@ module Cheffish
11
11
  end
12
12
 
13
13
  # Create or update the client/user
14
- current_public_key = new_json['public_key']
14
+ current_public_key = new_json["public_key"]
15
15
  differences = json_differences(current_json, new_json)
16
16
  if current_resource_exists?
17
17
  # Update the actor if it's different
@@ -19,7 +19,7 @@ module Cheffish
19
19
  description = [ "update #{actor_type} #{new_resource.name} at #{actor_path}" ] + differences
20
20
  converge_by description do
21
21
  result = rest.put("#{actor_path}/#{new_resource.name}", normalize_for_put(new_json))
22
- current_public_key, current_public_key_format = Cheffish::KeyFormatter.decode(result['public_key']) if result['public_key']
22
+ current_public_key, current_public_key_format = Cheffish::KeyFormatter.decode(result["public_key"]) if result["public_key"]
23
23
  end
24
24
  end
25
25
  else
@@ -30,7 +30,7 @@ module Cheffish
30
30
  description = [ "create #{actor_type} #{new_resource.name} at #{actor_path}" ] + differences
31
31
  converge_by description do
32
32
  result = rest.post("#{actor_path}", normalize_for_post(new_json))
33
- current_public_key, current_public_key_format = Cheffish::KeyFormatter.decode(result['public_key']) if result['public_key']
33
+ current_public_key, current_public_key_format = Cheffish::KeyFormatter.decode(result["public_key"]) if result["public_key"]
34
34
  end
35
35
  end
36
36
 
@@ -39,9 +39,9 @@ module Cheffish
39
39
  # TODO use inline_resource
40
40
  key_content = Cheffish::KeyFormatter.encode(current_public_key, { :format => new_resource.output_key_format })
41
41
  if !current_resource.output_key_path
42
- action = 'create'
42
+ action = "create"
43
43
  elsif key_content != IO.read(current_resource.output_key_path)
44
- action = 'overwrite'
44
+ action = "overwrite"
45
45
  else
46
46
  action = nil
47
47
  end
@@ -109,7 +109,7 @@ module Cheffish
109
109
 
110
110
  def augment_new_json(json)
111
111
  if new_public_key
112
- json['public_key'] = new_public_key.to_pem
112
+ json["public_key"] = new_public_key.to_pem
113
113
  end
114
114
  json
115
115
  end
@@ -1,4 +1,4 @@
1
- require 'cheffish/basic_chef_client'
1
+ require "cheffish/basic_chef_client"
2
2
 
3
3
  module Cheffish
4
4
  class ChefRun
@@ -11,7 +11,7 @@ module Cheffish
11
11
  # - log_location: <path|IO object> - where to stream logs to
12
12
  # - verbose_logging: true|false - true if you want verbose logging in :debug
13
13
  #
14
- def initialize(chef_config={})
14
+ def initialize(chef_config = {})
15
15
  @chef_config = chef_config || {}
16
16
  end
17
17
 
@@ -56,18 +56,23 @@ module Cheffish
56
56
  def stdout
57
57
  @client ? client.chef_config[:stdout].string : nil
58
58
  end
59
+
59
60
  def stderr
60
61
  @client ? client.chef_config[:stderr].string : nil
61
62
  end
63
+
62
64
  def logs
63
65
  @client ? client.chef_config[:log_location].string : nil
64
66
  end
67
+
65
68
  def logged_warnings
66
69
  logs.lines.select { |l| l =~ /^\[[^\]]*\] WARN:/ }.join("\n")
67
70
  end
71
+
68
72
  def logged_errors
69
73
  logs.lines.select { |l| l =~ /^\[[^\]]*\] ERROR:/ }.join("\n")
70
74
  end
75
+
71
76
  def logged_info
72
77
  logs.lines.select { |l| l =~ /^\[[^\]]*\] INFO:/ }.join("\n")
73
78
  end
@@ -1,5 +1,5 @@
1
- require 'chef/config'
2
- require 'cheffish/with_pattern'
1
+ require "chef/config"
2
+ require "cheffish/with_pattern"
3
3
 
4
4
  module Cheffish
5
5
  class ChefRunData
@@ -1,4 +1,4 @@
1
- require 'chef/event_dispatch/base'
1
+ require "chef/event_dispatch/base"
2
2
 
3
3
  module Cheffish
4
4
  class ChefRunListener < Chef::EventDispatch::Base
@@ -1,14 +1,14 @@
1
- require 'openssl'
2
- require 'net/ssh'
3
- require 'etc'
4
- require 'socket'
5
- require 'digest/md5'
6
- require 'base64'
1
+ require "openssl"
2
+ require "net/ssh"
3
+ require "etc"
4
+ require "socket"
5
+ require "digest/md5"
6
+ require "base64"
7
7
 
8
8
  module Cheffish
9
9
  class KeyFormatter
10
10
  # Returns nil or key, format
11
- def self.decode(str, pass_phrase=nil, filename='')
11
+ def self.decode(str, pass_phrase = nil, filename = "")
12
12
  key_format = {}
13
13
  key_format[:format] = format_of(str)
14
14
 
@@ -38,7 +38,7 @@ module Cheffish
38
38
  encode_openssh_key(key)
39
39
  when :pem
40
40
  if key_format[:pass_phrase]
41
- cipher = key_format[:cipher] || 'DES-EDE3-CBC'
41
+ cipher = key_format[:cipher] || "DES-EDE3-CBC"
42
42
  key.to_pem(OpenSSL::Cipher.new(cipher), key_format[:pass_phrase])
43
43
  else
44
44
  key.to_pem
@@ -48,44 +48,42 @@ module Cheffish
48
48
  when :fingerprint, :pkcs1md5fingerprint
49
49
  hexes = Digest::MD5.hexdigest(key.to_der)
50
50
  # Put : between every pair of hexes
51
- hexes.scan(/../).join(':')
51
+ hexes.scan(/../).join(":")
52
52
  when :rfc4716md5fingerprint
53
53
  type, base64_data, etc = encode_openssh_key(key).split
54
54
  data = Base64.decode64(base64_data)
55
55
  hexes = Digest::MD5.hexdigest(data)
56
- hexes.scan(/../).join(':')
56
+ hexes.scan(/../).join(":")
57
57
  when :pkcs8sha1fingerprint
58
58
  if RUBY_VERSION.to_f >= 2.0
59
59
  raise "PKCS8 SHA1 not supported in Ruby #{RUBY_VERSION}"
60
60
  end
61
- require 'openssl_pkcs8'
61
+ require "openssl_pkcs8"
62
62
  pkcs8_pem = key.to_pem_pkcs8
63
63
  pkcs8_base64 = pkcs8_pem.split("\n").reject { |l| l =~ /^-----/ }
64
64
  pkcs8_data = Base64.decode64(pkcs8_base64.join)
65
65
  hexes = Digest::SHA1.hexdigest(pkcs8_data)
66
- hexes.scan(/../).join(':')
66
+ hexes.scan(/../).join(":")
67
67
  else
68
68
  raise "Unrecognized key format #{format}"
69
69
  end
70
70
  end
71
71
 
72
- private
73
-
74
72
  def self.encode_openssh_key(key)
75
73
  # TODO there really isn't a method somewhere in net/ssh or openssl that does this??
76
74
  type = key.ssh_type
77
- data = [ key.to_blob ].pack('m0')
75
+ data = [ key.to_blob ].pack("m0")
78
76
  "#{type} #{data} #{Etc.getlogin}@#{Socket.gethostname}"
79
77
  end
80
78
 
81
- def self.decode_openssh_key(str, filename='')
79
+ def self.decode_openssh_key(str, filename = "")
82
80
  Net::SSH::KeyFactory.load_data_public_key(str, filename)
83
81
  end
84
82
 
85
83
  def self.format_of(key_contents)
86
- if key_contents.start_with?('-----BEGIN ')
84
+ if key_contents.start_with?("-----BEGIN ")
87
85
  :pem
88
- elsif key_contents.start_with?('ssh-rsa ') || key_contents.start_with?('ssh-dss ')
86
+ elsif key_contents.start_with?("ssh-rsa ", "ssh-dss ")
89
87
  :openssh
90
88
  else
91
89
  :der