cheffish 0.3 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5f6b8abbcddf03b097bc9380a4bad5367f760f2f
4
- data.tar.gz: 3f17d2781c140a66a869ecbedfd4c0c74326f1f9
3
+ metadata.gz: 2c99e67f4f2af51e4be1bb7f4d127973b0060789
4
+ data.tar.gz: e8547a16bc4df37aa4d29b00f6f36af3ec57c381
5
5
  SHA512:
6
- metadata.gz: 798aeb7bfd711164e71e613c2a3124aaf2cb2a8a344010aa6b97e17637802fc6ded341525677f97adc388f96360f7c28ce67145e519cf2ccc5b22fc199acd9b7
7
- data.tar.gz: 0cbe97227f83d68327b8023f4ba23eaa81459f034fe31f5ee3e9a69bdb395cfdaaf7785b3dc1a458513312d32ff8a984ef10a6a210133d4462f3a77728f5433a
6
+ metadata.gz: 5ac67f69abb511dab697a2a6d77b058dcfb665864d0d647b332a7a820cb59e576406fbabb1fb22a417c2dbb4cb66b7683d537ebe1b97dfa1779a4e985577dcea
7
+ data.tar.gz: 85e3d63ac54c4b1665d2b4957be6982731f1a701cab9709537e545890c7415331773c47ff187cbf31a1b5328813cd6c8c6d361ad1aa9a4404f8a73a49c1b0f89
@@ -5,11 +5,11 @@ require 'cheffish/key_formatter'
5
5
  class Chef::Provider::PrivateKey < Chef::Provider::LWRPBase
6
6
 
7
7
  action :create do
8
- create_key(false)
8
+ create_key(false, :create)
9
9
  end
10
10
 
11
11
  action :regenerate do
12
- create_key(true)
12
+ create_key(true, :regenerate)
13
13
  end
14
14
 
15
15
  action :delete do
@@ -26,7 +26,7 @@ class Chef::Provider::PrivateKey < Chef::Provider::LWRPBase
26
26
  true
27
27
  end
28
28
 
29
- def create_key(regenerate)
29
+ def create_key(regenerate, action)
30
30
  final_private_key = nil
31
31
  if new_source_key
32
32
  #
@@ -92,7 +92,7 @@ class Chef::Provider::PrivateKey < Chef::Provider::LWRPBase
92
92
  if new_resource.public_key_path
93
93
  public_key_path = new_resource.public_key_path
94
94
  public_key_format = new_resource.public_key_format
95
- Cheffish.inline_resource(self) do
95
+ Cheffish.inline_resource(self, action) do
96
96
  public_key public_key_path do
97
97
  source_key final_private_key
98
98
  format public_key_format
@@ -139,7 +139,7 @@ class Chef::Provider::PrivateKey < Chef::Provider::LWRPBase
139
139
  attr_reader :current_private_key
140
140
 
141
141
  def load_current_resource
142
- resource = Chef::Resource::PrivateKey.new(new_resource.name)
142
+ resource = Chef::Resource::PrivateKey.new(new_resource.name, run_context)
143
143
 
144
144
  if new_resource.path != :none && ::File.exist?(new_resource.path)
145
145
  resource.path new_resource.path
@@ -62,7 +62,7 @@ class Chef::Provider::PublicKey < Chef::Provider::LWRPBase
62
62
 
63
63
  def load_current_resource
64
64
  if ::File.exist?(new_resource.path)
65
- resource = Chef::Resource::PublicKey.new(new_resource.path)
65
+ resource = Chef::Resource::PublicKey.new(new_resource.path, run_context)
66
66
  begin
67
67
  key, key_format = Cheffish::KeyFormatter.decode(IO.read(new_resource.path), nil, new_resource.path)
68
68
  if key
@@ -9,7 +9,7 @@ class Chef::Resource::ChefClient < Chef::Resource::LWRPBase
9
9
 
10
10
  def initialize(*args)
11
11
  super
12
- chef_server Cheffish.enclosing_chef_server
12
+ chef_server run_context.cheffish.current_chef_server
13
13
  end
14
14
 
15
15
  # Client attributes
@@ -9,7 +9,7 @@ class Chef::Resource::ChefDataBag < Chef::Resource::LWRPBase
9
9
 
10
10
  def initialize(*args)
11
11
  super
12
- chef_server Cheffish.enclosing_chef_server
12
+ chef_server run_context.cheffish.current_chef_server
13
13
  end
14
14
 
15
15
  attribute :name, :kind_of => String, :regex => Cheffish::NAME_REGEX, :name_attribute => true
@@ -12,18 +12,18 @@ class Chef::Resource::ChefDataBagItem < Chef::Resource::LWRPBase
12
12
  super
13
13
  name @name
14
14
  if !data_bag
15
- data_bag Cheffish.enclosing_data_bag
15
+ data_bag run_context.cheffish.current_data_bag
16
16
  end
17
- if Cheffish.enclosing_data_bag_item_encryption
18
- @encrypt = true if Cheffish.enclosing_data_bag_item_encryption[:encrypt_all]
19
- @secret = Cheffish.enclosing_data_bag_item_encryption[:secret]
20
- @secret_path = Cheffish.enclosing_data_bag_item_encryption[:secret_path] || Chef::Config[:encrypted_data_bag_secret]
21
- @encryption_cipher = Cheffish.enclosing_data_bag_item_encryption[:encryption_cipher]
22
- @encryption_version = Cheffish.enclosing_data_bag_item_encryption[:encryption_version]
23
- @old_secret = Cheffish.enclosing_data_bag_item_encryption[:old_secret]
24
- @old_secret_path = Cheffish.enclosing_data_bag_item_encryption[:old_secret_path]
17
+ if run_context.cheffish.current_data_bag_item_encryption
18
+ @encrypt = true if run_context.cheffish.current_data_bag_item_encryption[:encrypt_all]
19
+ @secret = run_context.cheffish.current_data_bag_item_encryption[:secret]
20
+ @secret_path = run_context.cheffish.current_data_bag_item_encryption[:secret_path] || Chef::Config[:encrypted_data_bag_secret]
21
+ @encryption_cipher = run_context.cheffish.current_data_bag_item_encryption[:encryption_cipher]
22
+ @encryption_version = run_context.cheffish.current_data_bag_item_encryption[:encryption_version]
23
+ @old_secret = run_context.cheffish.current_data_bag_item_encryption[:old_secret]
24
+ @old_secret_path = run_context.cheffish.current_data_bag_item_encryption[:old_secret_path]
25
25
  end
26
- chef_server Cheffish.enclosing_chef_server
26
+ chef_server run_context.cheffish.current_chef_server
27
27
  end
28
28
 
29
29
  def name(*args)
@@ -10,7 +10,7 @@ class Chef::Resource::ChefEnvironment < Chef::Resource::LWRPBase
10
10
 
11
11
  def initialize(*args)
12
12
  super
13
- chef_server Cheffish.enclosing_chef_server
13
+ chef_server run_context.cheffish.current_chef_server
14
14
  end
15
15
 
16
16
  attribute :name, :kind_of => String, :regex => Cheffish::NAME_REGEX, :name_attribute => true
@@ -68,4 +68,4 @@ class Chef::Resource::ChefEnvironment < Chef::Resource::LWRPBase
68
68
 
69
69
  alias :attributes :default_attributes
70
70
  alias :attribute :default
71
- end
71
+ end
@@ -10,8 +10,8 @@ class Chef::Resource::ChefNode < Chef::Resource::LWRPBase
10
10
  # Grab environment from with_environment
11
11
  def initialize(*args)
12
12
  super
13
- chef_environment Cheffish.enclosing_environment
14
- chef_server Cheffish.enclosing_chef_server
13
+ chef_environment run_context.cheffish.current_environment
14
+ chef_server run_context.cheffish.current_chef_server
15
15
  end
16
16
 
17
17
  Cheffish.node_attributes(self)
@@ -11,7 +11,7 @@ class Chef::Resource::ChefRole < Chef::Resource::LWRPBase
11
11
  # Grab environment from with_environment
12
12
  def initialize(*args)
13
13
  super
14
- chef_server Cheffish.enclosing_chef_server
14
+ chef_server run_context.cheffish.current_chef_server
15
15
  end
16
16
 
17
17
  attribute :name, :kind_of => String, :regex => Cheffish::NAME_REGEX, :name_attribute => true
@@ -10,7 +10,7 @@ class Chef::Resource::ChefUser < Chef::Resource::LWRPBase
10
10
  # Grab environment from with_environment
11
11
  def initialize(*args)
12
12
  super
13
- chef_server Cheffish.enclosing_chef_server
13
+ chef_server run_context.cheffish.current_chef_server
14
14
  end
15
15
 
16
16
  # Client attributes
data/lib/cheffish.rb CHANGED
@@ -1,56 +1,11 @@
1
1
  require 'chef/run_list/run_list_item'
2
- require 'cheffish/inline_resource'
2
+ require 'cheffish/basic_chef_client'
3
3
 
4
4
  module Cheffish
5
5
  NAME_REGEX = /^[.\-[:alnum:]_]+$/
6
6
 
7
- @@enclosing_data_bag = nil
8
- def self.enclosing_data_bag
9
- @@enclosing_data_bag
10
- end
11
- def self.enclosing_data_bag=(name)
12
- @@enclosing_data_bag = name
13
- end
14
-
15
- @@enclosing_environment = nil
16
- def self.enclosing_environment
17
- @@enclosing_environment
18
- end
19
- def self.enclosing_environment=(name)
20
- @@enclosing_environment = name
21
- end
22
-
23
- @@enclosing_data_bag_item_encryption = nil
24
- def self.enclosing_data_bag_item_encryption
25
- @@enclosing_data_bag_item_encryption
26
- end
27
- def self.enclosing_data_bag_item_encryption=(options)
28
- @@enclosing_data_bag_item_encryption = options
29
- end
30
-
31
- def self.inline_resource(provider, &block)
32
- InlineResource.new(provider).instance_eval(&block)
33
- end
34
-
35
- @@enclosing_chef_server = nil
36
- def self.enclosing_chef_server
37
- @@enclosing_chef_server || {
38
- :chef_server_url => Chef::Config[:chef_server_url],
39
- :options => {
40
- :client_name => Chef::Config[:node_name],
41
- :signing_key_filename => Chef::Config[:client_key]
42
- }
43
- }
44
- end
45
- def self.enclosing_chef_server=(chef_server)
46
- @@enclosing_chef_server = chef_server
47
- end
48
-
49
- def self.reset
50
- @@enclosing_data_bag = nil
51
- @@enclosing_environment = nil
52
- @@enclosing_data_bag_item_encryption = nil
53
- @@enclosing_chef_server = nil
7
+ def self.inline_resource(provider, provider_action, &block)
8
+ BasicChefClient.inline_resource(provider, provider_action, &block)
54
9
  end
55
10
 
56
11
  NOT_PASSED=Object.new
@@ -0,0 +1,96 @@
1
+ require 'chef/dsl/recipe'
2
+ require 'chef/event_dispatch/base'
3
+ require 'chef/event_dispatch/dispatcher'
4
+ require 'chef/node'
5
+ require 'chef/run_context'
6
+ require 'chef/runner'
7
+ require 'forwardable'
8
+
9
+ module Cheffish
10
+ class BasicChefClient
11
+ include Chef::DSL::Recipe
12
+
13
+ def initialize(node = nil, events = nil)
14
+ if !node
15
+ node = Chef::Node.new
16
+ node.name 'basic_client'
17
+ node.automatic[:platform] = 'test'
18
+ node.automatic[:platform_version] = 'test'
19
+ end
20
+
21
+ @event_catcher = BasicChefClientEvents.new
22
+ dispatcher = Chef::EventDispatch::Dispatcher.new(@event_catcher)
23
+ dispatcher.register(events) if events
24
+ @run_context = Chef::RunContext.new(node, {}, dispatcher)
25
+ @updated = []
26
+ @cookbook_name = 'basic_client'
27
+ end
28
+
29
+ extend Forwardable
30
+
31
+ # Stuff recipes need
32
+ attr_reader :run_context
33
+ attr_accessor :cookbook_name
34
+ attr_accessor :recipe_name
35
+ def_delegators :@run_context, :resource_collection, :immediate_notifications, :delayed_notifications
36
+
37
+ def load_block(&block)
38
+ @recipe_name = 'block'
39
+ instance_eval(&block)
40
+ end
41
+
42
+ def converge
43
+ Chef::Runner.new(self).converge
44
+ end
45
+
46
+ def updates
47
+ @event_catcher.updates
48
+ end
49
+
50
+ def updated?
51
+ @event_catcher.updates.size > 0
52
+ end
53
+
54
+ def self.inline_resource(provider, provider_action, &block)
55
+ events = ProviderEventForwarder.new(provider, provider_action)
56
+ client = BasicChefClient.new(provider.node)
57
+ client.load_block(&block)
58
+ client.converge
59
+ client.updated?
60
+ end
61
+
62
+ def self.converge_block(node = nil, events = nil, &block)
63
+ client = BasicChefClient.new(node, events)
64
+ client.load_block(&block)
65
+ client.converge
66
+ client.updated?
67
+ end
68
+
69
+ class BasicChefClientEvents < Chef::EventDispatch::Base
70
+ def initialize
71
+ @updates = []
72
+ end
73
+
74
+ attr_reader :updates
75
+
76
+ # Called after a resource has been completely converged.
77
+ def resource_updated(resource, action)
78
+ updates << [ resource, action ]
79
+ end
80
+ end
81
+
82
+ class ProviderEventForwarder < Chef::EventDispatch::Base
83
+ def initialize(provider, provider_action)
84
+ @provider = provider
85
+ @provider_action = provider_action
86
+ end
87
+
88
+ attr_reader :provider
89
+ attr_reader :provider_action
90
+
91
+ def resource_update_applied(resource, action, update)
92
+ provider.run_context.events.resource_update_applied(provider.new_resource, provider_action, update)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -14,7 +14,7 @@ module Cheffish
14
14
  end
15
15
 
16
16
  def not_found_resource
17
- resource = resource_class.new(new_resource.name)
17
+ resource = resource_class.new(new_resource.name, run_context)
18
18
  resource.action :delete
19
19
  resource
20
20
  end
@@ -67,7 +67,7 @@ module Cheffish
67
67
  end
68
68
 
69
69
  def json_to_resource(json)
70
- resource = resource_class.new(new_resource.name)
70
+ resource = resource_class.new(new_resource.name, run_context)
71
71
  keys.each do |json_key, resource_key|
72
72
  resource.send(resource_key, json.delete(json_key))
73
73
  end
@@ -0,0 +1,25 @@
1
+ require 'chef/config'
2
+ require 'cheffish/with_pattern'
3
+
4
+ module Cheffish
5
+ class ChefRunData
6
+ def initialize
7
+ @local_servers = []
8
+ @current_chef_server = {
9
+ :chef_server_url => Chef::Config[:chef_server_url],
10
+ :options => {
11
+ :client_name => Chef::Config[:node_name],
12
+ :signing_key_filename => Chef::Config[:client_key]
13
+ }
14
+ }
15
+ end
16
+
17
+ extend Cheffish::WithPattern
18
+ with :data_bag
19
+ with :environment
20
+ with :data_bag_item_encryption
21
+ with :chef_server
22
+
23
+ attr_reader :local_servers
24
+ end
25
+ end
@@ -0,0 +1,28 @@
1
+ require 'chef/event_dispatch/base'
2
+
3
+ module Cheffish
4
+ class ChefRunListener < Chef::EventDispatch::Base
5
+ def initialize(run_context)
6
+ @run_context = run_context
7
+ end
8
+
9
+ attr_reader :run_context
10
+
11
+ def run_complete(node)
12
+ disconnect
13
+ end
14
+
15
+ def run_failed(exception)
16
+ disconnect
17
+ end
18
+
19
+ private
20
+
21
+ def disconnect
22
+ # Stop the servers
23
+ run_context.cheffish.local_servers.each do |server|
24
+ server.stop
25
+ end
26
+ end
27
+ end
28
+ end
@@ -3,6 +3,8 @@ require 'net/ssh'
3
3
  require 'etc'
4
4
  require 'socket'
5
5
  require 'digest/md5'
6
+ require 'base64'
7
+ require 'openssl_pkcs8'
6
8
 
7
9
  module Cheffish
8
10
  class KeyFormatter
@@ -44,10 +46,21 @@ module Cheffish
44
46
  end
45
47
  when :der
46
48
  key.to_der
47
- when :fingerprint
49
+ when :fingerprint, :pkcs1md5fingerprint
48
50
  hexes = Digest::MD5.hexdigest(key.to_der)
49
51
  # Put : between every pair of hexes
50
52
  hexes.scan(/../).join(':')
53
+ when :rfc4716md5fingerprint
54
+ type, base64_data, etc = encode_openssh_key(key).split
55
+ data = Base64.decode64(base64_data)
56
+ hexes = Digest::MD5.hexdigest(data)
57
+ hexes.scan(/../).join(':')
58
+ when :pkcs8sha1fingerprint
59
+ pkcs8_pem = key.to_pem_pkcs8
60
+ pkcs8_base64 = pkcs8_pem.split("\n").reject { |l| l =~ /^-----/ }
61
+ pkcs8_data = Base64.decode64(pkcs8_base64.join)
62
+ hexes = Digest::SHA1.hexdigest(pkcs8_data)
63
+ hexes.scan(/../).join(':')
51
64
  else
52
65
  raise "Unrecognized key format #{format}"
53
66
  end
@@ -3,109 +3,84 @@ require 'cheffish'
3
3
  require 'chef_zero/server'
4
4
  require 'chef/chef_fs/chef_fs_data_store'
5
5
  require 'chef/chef_fs/config'
6
+ require 'cheffish/chef_run_data'
7
+ require 'cheffish/chef_run_listener'
8
+ require 'chef/client'
6
9
 
7
10
  class Chef
8
- class Recipe
9
- def with_chef_data_bag(name)
10
- old_enclosing_data_bag = Cheffish.enclosing_data_bag
11
- Cheffish.enclosing_data_bag = name
12
- if block_given?
13
- begin
14
- yield
15
- ensure
16
- Cheffish.enclosing_data_bag = old_enclosing_data_bag
17
- end
11
+ module DSL
12
+ module Recipe
13
+ def with_chef_data_bag(name)
14
+ run_context.cheffish.with_data_bag(name, &block)
18
15
  end
19
- end
20
16
 
21
- def with_chef_environment(name)
22
- old_enclosing_environment = Cheffish.enclosing_environment
23
- Cheffish.enclosing_environment = name
24
- if block_given?
25
- begin
26
- yield
27
- ensure
28
- Cheffish.enclosing_environment = old_enclosing_environment
29
- end
17
+ def with_chef_environment(name, &block)
18
+ run_context.cheffish.with_environment(name, &block)
30
19
  end
31
- end
32
20
 
33
- def with_chef_data_bag_item_encryption(encryption_options)
34
- old_enclosing_data_bag_item_encryption = Cheffish.enclosing_data_bag_item_encryption
35
- Cheffish.enclosing_data_bag_item_encryption = encryption_options
36
- if block_given?
37
- begin
38
- yield
39
- ensure
40
- Cheffish.enclosing_data_bag_item_encryption = old_enclosing_data_bag_item_encryption
41
- end
21
+ def with_chef_data_bag_item_encryption(encryption_options, &block)
22
+ run_context.cheffish.with_data_bag_item_encryption(encryption_options, &block)
42
23
  end
43
- end
44
24
 
45
- def with_chef_server(server_url, options = {})
46
- old_enclosing_chef_server = Cheffish.enclosing_chef_server
47
- Cheffish.enclosing_chef_server = { :chef_server_url => server_url, :options => options }
48
- if block_given?
49
- begin
50
- yield
51
- ensure
52
- Cheffish.enclosing_chef_server = old_enclosing_chef_server
53
- end
25
+ def with_chef_server(server_url, options = {}, &block)
26
+ run_context.cheffish.with_chef_server({ :chef_server_url => server_url, :options => options }, &block)
54
27
  end
55
- end
56
28
 
57
- def with_chef_local_server(options, &block)
58
- options[:host] ||= '127.0.0.1'
59
- options[:log_level] ||= Chef::Log.level
60
- options[:port] ||= 8900
29
+ def with_chef_local_server(options, &block)
30
+ options[:host] ||= '127.0.0.1'
31
+ options[:log_level] ||= Chef::Log.level
32
+ options[:port] ||= 8900
61
33
 
62
- # Create the data store chef-zero will use
63
- options[:data_store] ||= begin
64
- if !options[:chef_repo_path]
65
- raise "chef_repo_path must be specified to with_chef_local_server"
66
- end
34
+ # Create the data store chef-zero will use
35
+ options[:data_store] ||= begin
36
+ if !options[:chef_repo_path]
37
+ raise "chef_repo_path must be specified to with_chef_local_server"
38
+ end
67
39
 
68
- # Ensure all paths are given
69
- %w(acl client cookbook container data_bag environment group node role).each do |type|
70
- options["#{type}_path".to_sym] ||= begin
71
- if options[:chef_repo_path].kind_of?(String)
72
- Chef::Config.path_join(options[:chef_repo_path], "#{type}s")
73
- else
74
- options[:chef_repo_path].map { |path| Chef::Config.path_join(path, "#{type}s")}
40
+ # Ensure all paths are given
41
+ %w(acl client cookbook container data_bag environment group node role).each do |type|
42
+ options["#{type}_path".to_sym] ||= begin
43
+ if options[:chef_repo_path].kind_of?(String)
44
+ Chef::Config.path_join(options[:chef_repo_path], "#{type}s")
45
+ else
46
+ options[:chef_repo_path].map { |path| Chef::Config.path_join(path, "#{type}s")}
47
+ end
75
48
  end
49
+ # Work around issue in earlier versions of ChefFS where it expects strings for these
50
+ # instead of symbols
51
+ options["#{type}_path"] = options["#{type}_path".to_sym]
76
52
  end
77
- # Work around issue in earlier versions of ChefFS where it expects strings for these
78
- # instead of symbols
79
- options["#{type}_path"] = options["#{type}_path".to_sym]
80
- end
81
53
 
82
- chef_fs = Chef::ChefFS::Config.new(options).local_fs
83
- chef_fs.write_pretty_json = true
84
- Chef::ChefFS::ChefFSDataStore.new(chef_fs)
85
- end
54
+ chef_fs = Chef::ChefFS::Config.new(options).local_fs
55
+ chef_fs.write_pretty_json = true
56
+ Chef::ChefFS::ChefFSDataStore.new(chef_fs)
57
+ end
86
58
 
87
- # Start the chef-zero server
88
- Chef::Log.info("Starting chef-zero on port #{options[:port]} with repository at #{options[:data_store].chef_fs.fs_description}")
89
- chef_zero_server = ChefZero::Server.new(options)
90
- chef_zero_server.start_background
59
+ # Start the chef-zero server
60
+ Chef::Log.info("Starting chef-zero on port #{options[:port]} with repository at #{options[:data_store].chef_fs.fs_description}")
61
+ chef_zero_server = ChefZero::Server.new(options)
62
+ chef_zero_server.start_background
91
63
 
92
- @@local_servers ||= []
93
- @@local_servers << chef_zero_server
64
+ run_context.cheffish.local_servers << chef_zero_server
94
65
 
95
- with_chef_server(chef_zero_server.url, &block)
66
+ with_chef_server(chef_zero_server.url, &block)
67
+ end
96
68
  end
69
+ end
97
70
 
98
- def self.stop_local_servers
99
- # Just in case we're running this out of order:
100
- @@local_servers ||= []
101
-
102
- # Stop the servers
103
- @@local_servers.each do |server|
104
- server.stop
71
+ class RunContext
72
+ def cheffish
73
+ @cheffish ||= begin
74
+ run_data = Cheffish::ChefRunData.new
75
+ events.register(Cheffish::ChefRunListener.new(self))
76
+ run_data
105
77
  end
106
-
107
- # Clean up after ourselves (don't want to stop a server twice)
108
- @@local_servers = []
109
78
  end
110
79
  end
80
+
81
+ Chef::Client.when_run_starts do |run_status|
82
+ # Pulling on cheffish_run_data makes it initialize right now
83
+ run_status.run_context.cheffish
84
+ end
85
+
111
86
  end
@@ -1,3 +1,3 @@
1
1
  module Cheffish
2
- VERSION = '0.3'
2
+ VERSION = '0.4'
3
3
  end
@@ -0,0 +1,21 @@
1
+ module Cheffish
2
+ module WithPattern
3
+ def with(symbol)
4
+ class_eval <<EOM
5
+ attr_accessor :current_#{symbol}
6
+
7
+ def with_#{symbol}(value)
8
+ old_value = self.current_#{symbol}
9
+ self.current_#{symbol} = value
10
+ if block_given?
11
+ begin
12
+ yield
13
+ ensure
14
+ self.current_#{symbol} = old_value
15
+ end
16
+ end
17
+ end
18
+ EOM
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,64 @@
1
+ require 'cheffish/key_formatter'
2
+ require 'support/key_support'
3
+
4
+ describe 'Cheffish fingerprint key formatter' do
5
+
6
+ # Sample key: 0x9a6fa4c43b328c3d04c1fbc0498539218b6728e41cd35f6d27d491ef705f0b2083dc1ac977da19f54ba82b044773f20667e9627c543abb3b41b6eb9e4318ca3c68f487bbd0f1c9eea9a3101b7d1d180983c5440ac4183e78e9e256fa687d8aac63b21617a4b02b35bf5e307a3b76961a16cd8493e923536b34cc2b2da8d45220d57ef2243b081b555b84f1da0ade0e896c2aa96911b41430b59eaf75dbffb7eaa7c5b3a686f2d47a24e3b7f1acb0844f84a2fedc63660ae366b800cd9448093d6b1d96503ebb7807b48257e16c3d8a7c9a8cc5dd63116aa673bd9e09754de09358486e743e34c6a3642eeb64b2208efc96df39151572557a75638bd059c21a55 = 0xd6e92677d4e1d2aa6d14f87b5f49ee6916c6b92411536254fae4a21e82eebb0a40600247c701c1c938b21ca9f25b7b330c35fded57b4de3a951e83329a80bdbf2ba138fe2f190bffce43967b5fa93b179367bcd15cb1db7f9e3ab62caca95dc9489b62bc0a10b53841b932455a43409f96eed90dc80abc8cce5593ead8f0a26d * 0xb7f68cd427045788d5e315375f71d3a416784ec2597776a60ed77c821294d9bd66e96658bdcb43072cee0c849d297bd9f94991738f1a0df313ceb51b093a9372f12a61987f40e7a03d773911deb270916a574962ae8ff4f2d8bfcedee1c885e9c3e54212471636a6330b05b78c3a7ddf96b013be389a08ab7971db2f68fb2689
7
+
8
+ sample_private_key = <<EOF
9
+ -----BEGIN RSA PRIVATE KEY-----
10
+ MIIEowIBAAKCAQEAmm+kxDsyjD0EwfvASYU5IYtnKOQc019tJ9SR73BfCyCD3BrJd9oZ9UuoKwRH
11
+ c/IGZ+lifFQ6uztBtuueQxjKPGj0h7vQ8cnuqaMQG30dGAmDxUQKxBg+eOniVvpofYqsY7IWF6Sw
12
+ KzW/XjB6O3aWGhbNhJPpI1NrNMwrLajUUiDVfvIkOwgbVVuE8doK3g6JbCqpaRG0FDC1nq912/+3
13
+ 6qfFs6aG8tR6JOO38aywhE+Eov7cY2YK42a4AM2USAk9ax2WUD67eAe0glfhbD2KfJqMxd1jEWqm
14
+ c72eCXVN4JNYSG50PjTGo2Qu62SyII78lt85FRVyVXp1Y4vQWcIaVQIDAQABAoIBABY+JC37FLGs
15
+ DCZgOvab0HmrWUVDbX9oDBGjhQ1GUvoISdWGqiOv7vMsXWEssZnabt/CdmPPwdG7nCBbWSTyyhXf
16
+ S/DMtTBN1CjsimJbJ7iRjj/4J9DMaRsDHI1IbYo/UcreGF55YsImcJSBSOmNj9rcE+eXYgmrdxJY
17
+ oZNm8IWPaZ1/8KdPHSq6/HfTzRxXhcGOMGnf3lGfzkzIbV9Ee88Lv9sSV3bYrOsWMNabOe2TeTpC
18
+ UTfFkC++0RkFjEDINSCnoCi+ybzHLUDnurANCwnRWLTVEAeffwNVmiDfgimuqFtzCInW5/5bOTPz
19
+ rBmcC6QAFbyk2WKAlY8Zd4SBYqECgYEA1ukmd9Th0qptFPh7X0nuaRbGuSQRU2JU+uSiHoLuuwpA
20
+ YAJHxwHByTiyHKnyW3szDDX97Ve03jqVHoMymoC9vyuhOP4vGQv/zkOWe1+pOxeTZ7zRXLHbf546
21
+ tiysqV3JSJtivAoQtThBuTJFWkNAn5bu2Q3ICryMzlWT6tjwom0CgYEAt/aM1CcEV4jV4xU3X3HT
22
+ pBZ4TsJZd3amDtd8ghKU2b1m6WZYvctDByzuDISdKXvZ+UmRc48aDfMTzrUbCTqTcvEqYZh/QOeg
23
+ PXc5Ed6ycJFqV0liro/08ti/zt7hyIXpw+VCEkcWNqYzCwW3jDp935awE744mgireXHbL2j7JokC
24
+ gYAOHErRTWHyYgw9dz8qd4E21y7/EvYsQmWP/5kBZdlk4HxvkVbDI0NlAdr39NSb2w/z+kuM3Nhc
25
+ Sv5lfXnCGTfcKHIyesX+4AHQujFUMmi7H4YnJoecjXT7ARmbwn0ntae0o7cs34BPVb1C+qEBFy9U
26
+ CyXtjHEY+15HYekPX2UVVQKBgBT8Nwxsdv5VSbDh1rM4lN//ADJb0UDjdAX1ZuqfnANKq9asKitc
27
+ aIUFBxK+ff8hdbgOQF1iUaKNvBC0cCUZXYCbKi5/6uRIh+r7ErOLJ+fXbr4OTQeEvHiHaTn8Ct2J
28
+ CSWjnWngWhRZ2TDEsi947Kr40ZUu+d34ZzcvWcWKwDuhAoGBAJzCRoGOu6YGy+rBPxaIg0vB+Grx
29
+ rxs0NeNqGdrzmyAPN35OHXYclPwfp+DbtbJHgGMRc/9VFPqW9PeTKjIByeEsXyrcdreR35AR/fwR
30
+ AUcSSKTvw+PobCpXhdkiw4TgJhFNuZnoC63FOjNqA5mu1ICZYBb4ZVlgUAgSmDQxSIgK
31
+ -----END RSA PRIVATE KEY-----
32
+ EOF
33
+ sample_public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCab6TEOzKMPQTB+8BJhTkhi2co5BzTX20n1JHvcF8LIIPcGsl32hn1S6grBEdz8gZn6WJ8VDq7O0G2655DGMo8aPSHu9Dxye6poxAbfR0YCYPFRArEGD546eJW+mh9iqxjshYXpLArNb9eMHo7dpYaFs2Ek+kjU2s0zCstqNRSINV+8iQ7CBtVW4Tx2greDolsKqlpEbQUMLWer3Xb/7fqp8Wzpoby1Hok47fxrLCET4Si/txjZgrjZrgAzZRICT1rHZZQPrt4B7SCV+FsPYp8mozF3WMRaqZzvZ4JdU3gk1hIbnQ+NMajZC7rZLIgjvyW3zkVFXJVenVji9BZwhpV"
34
+
35
+ def key_to_format(key, format)
36
+ keyobj, f = Cheffish::KeyFormatter.decode(key)
37
+ Cheffish::KeyFormatter.encode(keyobj, {:format => format})
38
+ end
39
+
40
+ context 'when computing key fingperprints' do
41
+
42
+ it 'computes the PKCS#8 SHA1 private key fingerprint correctly' do
43
+ expect(key_to_format(sample_private_key, :pkcs8sha1fingerprint)).to eq(
44
+ '88:7e:3a:bd:26:9f:b5:c5:d8:ae:52:f9:df:0b:64:a4:5c:17:0a:87')
45
+ end
46
+
47
+ it 'computes the PKCS#1 MD5 public key fingerprint correctly' do
48
+ expect(key_to_format(sample_public_key, :pkcs1md5fingerprint)).to eq(
49
+ '1f:e8:da:c1:16:c3:72:7d:90:e2:b7:64:c4:b4:55:20')
50
+ end
51
+
52
+ it 'computes the RFC4716 MD5 public key fingerprint correctly' do
53
+ expect(key_to_format(sample_public_key, :rfc4716md5fingerprint)).to eq(
54
+ 'b0:13:4f:da:cf:8c:dc:a7:4a:1f:d2:3a:51:92:cf:6b')
55
+ end
56
+
57
+ it 'defaults to the PKCS#1 MD5 public key fingerprint' do
58
+ expect(key_to_format(sample_public_key, :fingerprint)).to eq(
59
+ key_to_format(sample_public_key, :pkcs1md5fingerprint))
60
+ end
61
+
62
+ end
63
+
64
+ end
@@ -20,13 +20,21 @@ module SpecSupport
20
20
  @event_sink.events
21
21
  end
22
22
 
23
- def run_recipe(&block)
24
- node = Chef::Node.new
25
- node.name 'test'
26
- node.automatic[:platform] = 'test'
27
- node.automatic[:platform_version] = 'test'
23
+ def run_context
24
+ @run_context ||= begin
25
+ node = Chef::Node.new
26
+ node.name 'test'
27
+ node.automatic[:platform] = 'test'
28
+ node.automatic[:platform_version] = 'test'
29
+ Chef::RunContext.new(node, {}, Chef::EventDispatch::Dispatcher.new(event_sink))
30
+ end
31
+ end
32
+
33
+ def event_sink
28
34
  @event_sink ||= EventSink.new
29
- run_context = Chef::RunContext.new(node, {}, Chef::EventDispatch::Dispatcher.new(@event_sink))
35
+ end
36
+
37
+ def run_recipe(&block)
30
38
  recipe = Chef::Recipe.new('test', 'test', run_context)
31
39
  recipe.instance_eval(&block)
32
40
  Chef::Runner.new(run_context).converge
@@ -77,76 +85,7 @@ RSpec.configure do |config|
77
85
 
78
86
  config.before :each do
79
87
  Chef::Config.reset
80
- Cheffish.reset
81
88
  end
82
89
  end
83
90
 
84
- # Stuff that should have been required in Chef, but wasn't (Chef will be fixed)
85
- require 'chef/platform'
86
-
87
- require 'chef/provider/service/simple'
88
- require 'chef/provider/service/init'
89
-
90
- require 'chef/provider/batch'
91
- require 'chef/provider/cron'
92
- require 'chef/provider/cron/aix'
93
- require 'chef/provider/cron/solaris'
94
- require 'chef/provider/directory'
95
- require 'chef/provider/env/windows'
96
- require 'chef/provider/erl_call'
97
- require 'chef/provider/execute'
98
- require 'chef/provider/file'
99
- require 'chef/provider/group/aix'
100
- require 'chef/provider/group/dscl'
101
- require 'chef/provider/group/gpasswd'
102
- require 'chef/provider/group/groupmod'
103
- require 'chef/provider/group/pw'
104
- require 'chef/provider/group/suse'
105
- require 'chef/provider/group/usermod'
106
- require 'chef/provider/group/windows'
107
- require 'chef/provider/http_request'
108
- require 'chef/provider/ifconfig'
109
- require 'chef/provider/ifconfig/aix'
110
- require 'chef/provider/ifconfig/debian'
111
- require 'chef/provider/ifconfig/redhat'
112
- require 'chef/provider/link'
113
- require 'chef/provider/log'
114
- require 'chef/provider/mdadm'
115
- require 'chef/provider/mount/aix'
116
- require 'chef/provider/mount/mount'
117
- require 'chef/provider/mount/windows'
118
- require 'chef/provider/package/aix'
119
- require 'chef/provider/package/apt'
120
- require 'chef/provider/package/freebsd'
121
- require 'chef/provider/package/ips'
122
- require 'chef/provider/package/macports'
123
- require 'chef/provider/package/pacman'
124
- require 'chef/provider/package/portage'
125
- require 'chef/provider/package/solaris'
126
- require 'chef/provider/package/smartos'
127
- require 'chef/provider/package/yum'
128
- require 'chef/provider/package/zypper'
129
- require 'chef/provider/powershell_script'
130
- require 'chef/provider/remote_directory'
131
- require 'chef/provider/route'
132
- require 'chef/provider/ruby_block'
133
- require 'chef/provider/script'
134
- require 'chef/provider/service/arch'
135
- require 'chef/provider/service/debian'
136
- require 'chef/provider/service/freebsd'
137
- require 'chef/provider/service/gentoo'
138
- require 'chef/provider/service/init'
139
- require 'chef/provider/service/insserv'
140
- require 'chef/provider/service/macosx'
141
- require 'chef/provider/service/redhat'
142
- require 'chef/provider/service/solaris'
143
- require 'chef/provider/service/systemd'
144
- require 'chef/provider/service/upstart'
145
- require 'chef/provider/service/windows'
146
- require 'chef/provider/template'
147
- require 'chef/provider/user/dscl'
148
- require 'chef/provider/user/pw'
149
- require 'chef/provider/user/useradd'
150
- require 'chef/provider/user/solaris'
151
- require 'chef/provider/user/windows'
152
- require 'chef/provider/whyrun_safe_ruby_block'
91
+ require 'chef/providers'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cheffish
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.3'
4
+ version: '0.4'
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Keiser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-24 00:00:00.000000000 Z
11
+ date: 2014-05-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: openssl_pkcs8
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -83,13 +97,17 @@ files:
83
97
  - lib/chef/resource/private_key.rb
84
98
  - lib/chef/resource/public_key.rb
85
99
  - lib/cheffish/actor_provider_base.rb
100
+ - lib/cheffish/basic_chef_client.rb
86
101
  - lib/cheffish/chef_provider_base.rb
102
+ - lib/cheffish/chef_run_data.rb
103
+ - lib/cheffish/chef_run_listener.rb
87
104
  - lib/cheffish/cheffish_server_api.rb
88
- - lib/cheffish/inline_resource.rb
89
105
  - lib/cheffish/key_formatter.rb
90
106
  - lib/cheffish/recipe_dsl.rb
91
107
  - lib/cheffish/version.rb
108
+ - lib/cheffish/with_pattern.rb
92
109
  - lib/cheffish.rb
110
+ - spec/functional/fingerprint_spec.rb
93
111
  - spec/integration/chef_client_spec.rb
94
112
  - spec/integration/chef_node_spec.rb
95
113
  - spec/integration/chef_user_spec.rb
@@ -1,88 +0,0 @@
1
- module Cheffish
2
- class InlineResource
3
- def initialize(provider)
4
- @provider = provider
5
- end
6
-
7
- attr_reader :provider
8
-
9
- def run_context
10
- provider.run_context
11
- end
12
-
13
- def method_missing(method_symbol, *args, &block)
14
- # Stolen ruthlessly from Chef's chef/dsl/recipe.rb
15
-
16
- # Checks the new platform => short_name => resource mapping initially
17
- # then fall back to the older approach (Chef::Resource.const_get) for
18
- # backward compatibility
19
- resource_class = Chef::Resource.resource_for_node(method_symbol, provider.run_context.node)
20
-
21
- super unless resource_class
22
- raise ArgumentError, "You must supply a name when declaring a #{method_symbol} resource" unless args.size > 0
23
-
24
- # If we have a resource like this one, we want to steal its state
25
- args << run_context
26
- resource = resource_class.new(*args)
27
- resource.source_line = caller[0]
28
- resource.load_prior_resource
29
- resource.cookbook_name = provider.cookbook_name
30
- resource.recipe_name = @recipe_name
31
- resource.params = @params
32
- # Determine whether this resource is being created in the context of an enclosing Provider
33
- resource.enclosing_provider = provider.is_a?(Chef::Provider) ? provider : nil
34
- # Evaluate resource attribute DSL
35
- resource.instance_eval(&block) if block
36
-
37
- # Run optional resource hook
38
- resource.after_created
39
-
40
- # Do NOT put this in the resource collection.
41
- #run_context.resource_collection.insert(resource)
42
-
43
- # Instead, run the action directly.
44
- Array(resource.action).each do |action|
45
- resource.updated_by_last_action(false)
46
- run_provider_action(resource.provider_for_action(action))
47
- provider.new_resource.updated_by_last_action(true) if resource.updated_by_last_action?
48
- end
49
- resource
50
- end
51
-
52
- # Do Chef::Provider.run_action, but without events
53
- def run_provider_action(inline_provider)
54
- if !inline_provider.whyrun_supported?
55
- raise "#{inline_provider} is not why-run-safe. Only why-run-safe resources are supported in inline_resource."
56
- end
57
-
58
- # Blatantly ripped off from chef/provider run_action
59
-
60
- # TODO: it would be preferable to get the action to be executed in the
61
- # constructor...
62
-
63
- # user-defined LWRPs may include unsafe load_current_resource methods that cannot be run in whyrun mode
64
- inline_provider.load_current_resource
65
- inline_provider.define_resource_requirements
66
- inline_provider.process_resource_requirements
67
-
68
- # user-defined providers including LWRPs may
69
- # not include whyrun support - if they don't support it
70
- # we can't execute any actions while we're running in
71
- # whyrun mode. Instead we 'fake' whyrun by documenting that
72
- # we can't execute the action.
73
- # in non-whyrun mode, this will still cause the action to be
74
- # executed normally.
75
- if inline_provider.whyrun_supported? && !inline_provider.requirements.action_blocked?(@action)
76
- inline_provider.send("action_#{inline_provider.action}")
77
- elsif !inline_provider.whyrun_mode?
78
- inline_provider.send("action_#{inline_provider.action}")
79
- end
80
-
81
- if inline_provider.resource_updated?
82
- inline_provider.new_resource.updated_by_last_action(true)
83
- end
84
-
85
- inline_provider.cleanup_after_converge
86
- end
87
- end
88
- end