cheffish 0.4.1 → 0.5.beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 119b0502e35e57dd3580bcbeb00dba88f64be3f5
4
+ data.tar.gz: eb28bbbc909edce3f303cf9783a591fd957c35c9
5
+ SHA512:
6
+ metadata.gz: c7cce6bb368c8c1efcabcd26f315d4b7cbee59f5956370efa2e60331086b3d0c6d0236c4585d5d3915dc1c37ece13d12b50a2543d72c04b7cde4f213ea49e2f1
7
+ data.tar.gz: 6e6522c74eee08367fd73d063af1d57b18ec2d017617a1ef62bbaccf87b18decf3e75788f6c3743847ee7f1eaf720f2df84e8ad8bdeb217c4c382f09a9cfcb5a
@@ -152,12 +152,12 @@ class Chef::Provider::ChefDataBagItem < Cheffish::ChefProviderBase
152
152
  end
153
153
 
154
154
  def encrypt(json, secret, version)
155
- old_version = Chef::Config[:data_bag_encrypt_version]
156
- Chef::Config[:data_bag_encrypt_version] = version
155
+ old_version = run_context.config[:data_bag_encrypt_version]
156
+ run_context.config[:data_bag_encrypt_version] = version
157
157
  begin
158
158
  Chef::EncryptedDataBagItem.encrypt_data_bag_item(json, secret)
159
159
  ensure
160
- Chef::Config[:data_bag_encrypt_version] = old_version
160
+ run_context.config[:data_bag_encrypt_version] = old_version
161
161
  end
162
162
  end
163
163
 
@@ -270,4 +270,4 @@ class Chef::Provider::ChefDataBagItem < Cheffish::ChefProviderBase
270
270
  FakeEntry.new("#{new_resource.id}.json", FakeEntry.new(new_resource.data_bag))
271
271
  end
272
272
 
273
- end
273
+ end
@@ -14,8 +14,8 @@ class Chef::Provider::PrivateKey < Chef::Provider::LWRPBase
14
14
 
15
15
  action :delete do
16
16
  if Array(current_resource.action) == [ :create ]
17
- converge_by "delete private key #{new_resource.path}" do
18
- ::File.unlink(new_resource.path)
17
+ converge_by "delete private key #{new_path}" do
18
+ ::File.unlink(new_path)
19
19
  end
20
20
  end
21
21
  end
@@ -27,15 +27,21 @@ class Chef::Provider::PrivateKey < Chef::Provider::LWRPBase
27
27
  end
28
28
 
29
29
  def create_key(regenerate, action)
30
+ if @should_create_directory
31
+ Cheffish.inline_resource(self, action) do
32
+ directory run_context.config[:private_key_write_path]
33
+ end
34
+ end
35
+
30
36
  final_private_key = nil
31
37
  if new_source_key
32
38
  #
33
39
  # Create private key from source
34
40
  #
35
41
  desired_output = encode_private_key(new_source_key)
36
- if Array(current_resource.action) == [ :delete ] || desired_output != IO.read(new_resource.path)
37
- converge_by "reformat key at #{new_resource.source_key_path} to #{new_resource.format} private key #{new_resource.path} (#{new_resource.pass_phrase ? ", #{new_resource.cipher} password" : ""})" do
38
- IO.write(new_resource.path, desired_output)
42
+ if Array(current_resource.action) == [ :delete ] || desired_output != IO.read(new_path)
43
+ converge_by "reformat key at #{new_resource.source_key_path} to #{new_resource.format} private key #{new_path} (#{new_resource.pass_phrase ? ", #{new_resource.cipher} password" : ""})" do
44
+ IO.write(new_path, desired_output)
39
45
  end
40
46
  end
41
47
 
@@ -50,7 +56,7 @@ class Chef::Provider::PrivateKey < Chef::Provider::LWRPBase
50
56
  (current_resource.size != new_resource.size ||
51
57
  current_resource.type != new_resource.type))
52
58
  action = (Array(current_resource.action) == [ :delete ]) ? "create" : "overwrite"
53
- converge_by "#{action} #{new_resource.type} private key #{new_resource.path} (#{new_resource.size} bits#{new_resource.pass_phrase ? ", #{new_resource.cipher} password" : ""})" do
59
+ converge_by "#{action} #{new_resource.type} private key #{new_path} (#{new_resource.size} bits#{new_resource.pass_phrase ? ", #{new_resource.cipher} password" : ""})" do
54
60
  case new_resource.type
55
61
  when :rsa
56
62
  if new_resource.exponent
@@ -62,7 +68,7 @@ class Chef::Provider::PrivateKey < Chef::Provider::LWRPBase
62
68
  final_private_key = OpenSSL::PKey::DSA.generate(new_resource.size)
63
69
  end
64
70
 
65
- if new_resource.path != :none
71
+ if new_path != :none
66
72
  write_private_key(final_private_key)
67
73
  end
68
74
  end
@@ -77,13 +83,13 @@ class Chef::Provider::PrivateKey < Chef::Provider::LWRPBase
77
83
  final_private_key = current_private_key
78
84
 
79
85
  if current_resource.format != new_resource.format
80
- converge_by "change format of #{new_resource.type} private key #{new_resource.path} from #{current_resource.format} to #{new_resource.format}" do
86
+ converge_by "change format of #{new_resource.type} private key #{new_path} from #{current_resource.format} to #{new_resource.format}" do
81
87
  write_private_key(current_private_key)
82
88
  end
83
89
  elsif (@current_file_mode & 0077) != 0
84
90
  new_mode = @current_file_mode & 07700
85
- converge_by "change mode of private key #{new_resource.path} to #{new_mode.to_s(8)}" do
86
- ::File.chmod(new_mode, new_resource.path)
91
+ converge_by "change mode of private key #{new_path} to #{new_mode.to_s(8)}" do
92
+ ::File.chmod(new_mode, new_path)
87
93
  end
88
94
  end
89
95
  end
@@ -114,7 +120,7 @@ class Chef::Provider::PrivateKey < Chef::Provider::LWRPBase
114
120
  end
115
121
 
116
122
  def write_private_key(key)
117
- ::File.open(new_resource.path, 'w') do |file|
123
+ ::File.open(new_path, 'w') do |file|
118
124
  file.chmod(0600)
119
125
  file.write(encode_private_key(key))
120
126
  end
@@ -138,14 +144,26 @@ class Chef::Provider::PrivateKey < Chef::Provider::LWRPBase
138
144
 
139
145
  attr_reader :current_private_key
140
146
 
147
+ def new_path
148
+ path = new_resource.path
149
+ if path.is_a?(Symbol)
150
+ path
151
+ elsif Pathname.new(path).relative? && run_context.config[:private_key_write_path]
152
+ @should_create_directory = true
153
+ ::File.join(run_context.config[:private_key_write_path], path)
154
+ else
155
+ path
156
+ end
157
+ end
158
+
141
159
  def load_current_resource
142
160
  resource = Chef::Resource::PrivateKey.new(new_resource.name, run_context)
143
161
 
144
- if new_resource.path != :none && ::File.exist?(new_resource.path)
145
- resource.path new_resource.path
162
+ if new_path != :none && ::File.exist?(new_path)
163
+ resource.path new_path
146
164
 
147
165
  begin
148
- key, key_format = Cheffish::KeyFormatter.decode(IO.read(new_resource.path), new_resource.pass_phrase, new_resource.path)
166
+ key, key_format = Cheffish::KeyFormatter.decode(IO.read(new_path), new_resource.pass_phrase, new_path)
149
167
  if key
150
168
  @current_private_key = key
151
169
  resource.format key_format[:format]
@@ -155,7 +173,7 @@ class Chef::Provider::PrivateKey < Chef::Provider::LWRPBase
155
173
  resource.pass_phrase key_format[:pass_phrase]
156
174
  resource.cipher key_format[:cipher]
157
175
  end
158
- @current_file_mode = ::File.stat(new_resource.path).mode
176
+ @current_file_mode = ::File.stat(new_path).mode
159
177
  rescue
160
178
  # If there's an error reading, we assume format and type are wrong and don't futz with them
161
179
  end
@@ -17,9 +17,9 @@ class Chef::Resource::ChefDataBagItem < Chef::Resource::LWRPBase
17
17
  if run_context.cheffish.current_data_bag_item_encryption
18
18
  @encrypt = true if run_context.cheffish.current_data_bag_item_encryption[:encrypt_all]
19
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]
20
+ @secret_path = run_context.cheffish.current_data_bag_item_encryption[:secret_path] || run_context.config[:encrypted_data_bag_secret]
21
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]
22
+ @encryption_version = run_context.cheffish.current_data_bag_item_encryption[:encryption_version] || run_context.config[:data_bag_encrypt_version]
23
23
  @old_secret = run_context.cheffish.current_data_bag_item_encryption[:old_secret]
24
24
  @old_secret_path = run_context.cheffish.current_data_bag_item_encryption[:old_secret_path]
25
25
  end
@@ -81,7 +81,7 @@ class Chef::Resource::ChefDataBagItem < Chef::Resource::LWRPBase
81
81
  @encrypt = true if @encrypt.nil?
82
82
  end
83
83
  end
84
- attribute :encryption_version, :kind_of => Integer, :default => Chef::Config[:data_bag_encrypt_version]
84
+ attribute :encryption_version, :kind_of => Integer
85
85
 
86
86
  # Old secret (or secrets) to read the old data bag when we are changing keys and re-encrypting data
87
87
  attribute :old_secret, :kind_of => [String, Array]
@@ -6,6 +6,8 @@ require 'chef/node'
6
6
  require 'chef/run_context'
7
7
  require 'chef/runner'
8
8
  require 'forwardable'
9
+ require 'chef/providers'
10
+ require 'chef/resources'
9
11
 
10
12
  module Cheffish
11
13
  class BasicChefClient
@@ -1,12 +1,11 @@
1
1
  require 'chef/config'
2
2
  require 'chef/run_list'
3
3
  require 'chef/provider/lwrp_base'
4
- require 'cheffish/cheffish_server_api'
5
4
 
6
5
  module Cheffish
7
6
  class ChefProviderBase < Chef::Provider::LWRPBase
8
7
  def rest
9
- @rest ||= CheffishServerAPI.new(new_resource.chef_server)
8
+ @rest ||= Cheffish.chef_server_api(new_resource.chef_server, run_context.config)
10
9
  end
11
10
 
12
11
  def current_resource_exists?
@@ -3,9 +3,9 @@ require 'cheffish/with_pattern'
3
3
 
4
4
  module Cheffish
5
5
  class ChefRunData
6
- def initialize
6
+ def initialize(config)
7
7
  @local_servers = []
8
- @current_chef_server = Cheffish.default_chef_server
8
+ @current_chef_server = Cheffish.default_chef_server(config)
9
9
  end
10
10
 
11
11
  extend Cheffish::WithPattern
@@ -0,0 +1,70 @@
1
+ module Cheffish
2
+ class MergedConfig
3
+ def initialize(*configs)
4
+ @configs = configs
5
+ @merge_arrays = {}
6
+ end
7
+
8
+ attr_reader :configs
9
+ def merge_arrays(*symbols)
10
+ symbols.each do |symbol|
11
+ @merge_arrays[symbol] = true
12
+ end
13
+ end
14
+
15
+ def [](name)
16
+ if @merge_arrays[name]
17
+ configs.select { |c| !c[name].nil? }.collect_concat { |c| c[name] }
18
+ else
19
+ result_configs = []
20
+ configs.each do |config|
21
+ value = config[name]
22
+ if !value.nil?
23
+ if value.respond_to?(:keys)
24
+ result_configs << value
25
+ elsif result_configs.size > 0
26
+ return result_configs[0]
27
+ else
28
+ return value
29
+ end
30
+ end
31
+ end
32
+ if result_configs.size > 1
33
+ MergedConfig.new(*result_configs)
34
+ elsif result_configs.size == 1
35
+ result_configs[0]
36
+ else
37
+ nil
38
+ end
39
+ end
40
+ end
41
+
42
+ def method_missing(name)
43
+ self[name]
44
+ end
45
+
46
+ def has_key?(name)
47
+ configs.any? { config.has_key?(name) }
48
+ end
49
+
50
+ def keys
51
+ configs.map { |c| c.keys }.flatten(1).uniq
52
+ end
53
+
54
+ def values
55
+ keys.map { |key| self[key] }
56
+ end
57
+
58
+ def each_pair(&block)
59
+ each(&block)
60
+ end
61
+
62
+ def each
63
+ keys.each do |key|
64
+ if block_given?
65
+ yield key, self[key]
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -6,6 +6,8 @@ require 'chef/chef_fs/config'
6
6
  require 'cheffish/chef_run_data'
7
7
  require 'cheffish/chef_run_listener'
8
8
  require 'chef/client'
9
+ require 'chef/config'
10
+ require 'cheffish/merged_config'
9
11
 
10
12
  class Chef
11
13
  module DSL
@@ -41,9 +43,9 @@ class Chef
41
43
  %w(acl client cookbook container data_bag environment group node role).each do |type|
42
44
  options["#{type}_path".to_sym] ||= begin
43
45
  if options[:chef_repo_path].kind_of?(String)
44
- Chef::Config.path_join(options[:chef_repo_path], "#{type}s")
46
+ run_context.config.path_join(options[:chef_repo_path], "#{type}s")
45
47
  else
46
- options[:chef_repo_path].map { |path| Chef::Config.path_join(path, "#{type}s")}
48
+ options[:chef_repo_path].map { |path| run_context.config.path_join(path, "#{type}s")}
47
49
  end
48
50
  end
49
51
  # Work around issue in earlier versions of ChefFS where it expects strings for these
@@ -68,14 +70,25 @@ class Chef
68
70
  end
69
71
  end
70
72
 
73
+ class Config
74
+ default(:profile) { ENV['CHEF_PROFILE'] || 'default' }
75
+ configurable(:private_keys)
76
+ default(:private_key_paths) { [ path_join(config_dir, 'keys'), path_join(user_home, '.ssh') ] }
77
+ default(:private_key_write_path) { private_key_paths.first }
78
+ end
79
+
71
80
  class RunContext
72
81
  def cheffish
73
82
  @cheffish ||= begin
74
- run_data = Cheffish::ChefRunData.new
83
+ run_data = Cheffish::ChefRunData.new(config)
75
84
  events.register(Cheffish::ChefRunListener.new(self))
76
85
  run_data
77
86
  end
78
87
  end
88
+
89
+ def config
90
+ @config ||= Cheffish.profiled_config(Chef::Config)
91
+ end
79
92
  end
80
93
 
81
94
  Chef::Client.when_run_starts do |run_status|
@@ -1,3 +1,3 @@
1
1
  module Cheffish
2
- VERSION = '0.4.1'
2
+ VERSION = '0.5.beta'
3
3
  end
data/lib/cheffish.rb CHANGED
@@ -1,5 +1,10 @@
1
1
  require 'chef/run_list/run_list_item'
2
2
  require 'cheffish/basic_chef_client'
3
+ require 'chef/server_api'
4
+ require 'chef/knife'
5
+ require 'chef/config_fetcher'
6
+ require 'chef/log'
7
+ require 'chef/application'
3
8
 
4
9
  module Cheffish
5
10
  NAME_REGEX = /^[.\-[:alnum:]_]+$/
@@ -8,16 +13,67 @@ module Cheffish
8
13
  BasicChefClient.inline_resource(provider, provider_action, &block)
9
14
  end
10
15
 
11
- def self.default_chef_server
16
+ def self.default_chef_server(config = profiled_config)
12
17
  {
13
- :chef_server_url => Chef::Config[:chef_server_url],
18
+ :chef_server_url => config[:chef_server_url],
14
19
  :options => {
15
- :client_name => Chef::Config[:node_name],
16
- :signing_key_filename => Chef::Config[:client_key]
20
+ :client_name => config[:node_name],
21
+ :signing_key_filename => config[:client_key]
17
22
  }
18
23
  }
19
24
  end
20
25
 
26
+ def self.chef_server_api(chef_server_hash = default_chef_server, config = Chef::Config)
27
+ Chef::ServerAPI.new(config[:chef_server_url], :client_name => config[:node_name], :signing_key_filename => config[:client_key])
28
+ end
29
+
30
+ def self.profiled_config(config = Chef::Config)
31
+ if config.profile && config.profiles && config.profiles[config.profile]
32
+ MergedConfig.new(config.profiles[config.profile], config)
33
+ else
34
+ config
35
+ end
36
+ end
37
+
38
+ def self.load_chef_config(chef_config = Chef::Config)
39
+ chef_config.config_file = Chef::Knife.locate_config_file
40
+ config_fetcher = Chef::ConfigFetcher.new(chef_config.config_file, chef_config.config_file_jail)
41
+ if chef_config.config_file.nil?
42
+ Chef::Log.warn("No config file found or specified on command line, using command line options.")
43
+ elsif config_fetcher.config_missing?
44
+ Chef::Log.warn("Did not find config file: #{chef_config.config_file}, using command line options.")
45
+ else
46
+ config_content = config_fetcher.read_config
47
+ config_file_path = chef_config.config_file
48
+ begin
49
+ chef_config.from_string(config_content, config_file_path)
50
+ rescue Exception => error
51
+ Chef::Log.fatal("Configuration error #{error.class}: #{error.message}")
52
+ filtered_trace = error.backtrace.grep(/#{Regexp.escape(config_file_path)}/)
53
+ filtered_trace.each {|line| Chef::Log.fatal(" " + line )}
54
+ Chef::Application.fatal!("Aborting due to error in '#{config_file_path}'", 2)
55
+ end
56
+ end
57
+ Cheffish.profiled_config(chef_config)
58
+ end
59
+
60
+ def self.honor_local_mode(local_mode_default = true)
61
+ if !Chef::Config.has_key?(:local_mode) && !local_mode_default.nil?
62
+ Chef::Config.local_mode = default
63
+ end
64
+ if Chef::Config.local_mode && !Chef::Config.has_key?(:cookbook_path) && !Chef::Config.has_key?(:chef_repo_path)
65
+ Chef::Config.chef_repo_path = Chef::Config.find_chef_repo_path(Dir.pwd)
66
+ end
67
+ Chef::Application.setup_server_connectivity
68
+ if block_given?
69
+ begin
70
+ yield
71
+ ensure
72
+ Chef::Application.destroy_server_connectivity
73
+ end
74
+ end
75
+ end
76
+
21
77
  NOT_PASSED=Object.new
22
78
 
23
79
  def self.node_attributes(klass)
metadata CHANGED
@@ -1,78 +1,69 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cheffish
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
5
- prerelease:
4
+ version: 0.5.beta
6
5
  platform: ruby
7
6
  authors:
8
7
  - John Keiser
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2014-05-07 00:00:00.000000000 Z
11
+ date: 2014-05-23 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: chef
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: openssl_pkcs8
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - '>='
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - '>='
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: rake
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: rspec
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ! '>='
59
+ - - '>='
68
60
  - !ruby/object:Gem::Version
69
61
  version: '0'
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ! '>='
66
+ - - '>='
76
67
  - !ruby/object:Gem::Version
77
68
  version: '0'
78
69
  description: A library to manipulate Chef in Chef.
@@ -110,8 +101,8 @@ files:
110
101
  - lib/cheffish/chef_provider_base.rb
111
102
  - lib/cheffish/chef_run_data.rb
112
103
  - lib/cheffish/chef_run_listener.rb
113
- - lib/cheffish/cheffish_server_api.rb
114
104
  - lib/cheffish/key_formatter.rb
105
+ - lib/cheffish/merged_config.rb
115
106
  - lib/cheffish/recipe_dsl.rb
116
107
  - lib/cheffish/version.rb
117
108
  - lib/cheffish/with_pattern.rb
@@ -126,27 +117,26 @@ files:
126
117
  - spec/support/spec_support.rb
127
118
  homepage: http://wiki.opscode.com/display/chef
128
119
  licenses: []
120
+ metadata: {}
129
121
  post_install_message:
130
122
  rdoc_options: []
131
123
  require_paths:
132
124
  - lib
133
125
  required_ruby_version: !ruby/object:Gem::Requirement
134
- none: false
135
126
  requirements:
136
- - - ! '>='
127
+ - - '>='
137
128
  - !ruby/object:Gem::Version
138
129
  version: '0'
139
130
  required_rubygems_version: !ruby/object:Gem::Requirement
140
- none: false
141
131
  requirements:
142
- - - ! '>='
132
+ - - '>'
143
133
  - !ruby/object:Gem::Version
144
- version: '0'
134
+ version: 1.3.1
145
135
  requirements: []
146
136
  rubyforge_project:
147
- rubygems_version: 1.8.23
137
+ rubygems_version: 2.0.3
148
138
  signing_key:
149
- specification_version: 3
139
+ specification_version: 4
150
140
  summary: A library to manipulate Chef in Chef.
151
141
  test_files: []
152
142
  has_rdoc:
@@ -1,21 +0,0 @@
1
- require 'chef/http'
2
- require 'chef/http/authenticator'
3
- require 'chef/http/cookie_manager'
4
- require 'chef/http/decompressor'
5
- require 'chef/http/json_input'
6
- require 'chef/http/json_output'
7
-
8
- module Cheffish
9
- # Just like ServerAPI, except it does not default the server URL or options
10
- class CheffishServerAPI < Chef::HTTP
11
- def initialize(chef_server)
12
- super(chef_server[:chef_server_url], chef_server[:options] || {})
13
- end
14
-
15
- use Chef::HTTP::JSONInput
16
- use Chef::HTTP::JSONOutput
17
- use Chef::HTTP::CookieManager
18
- use Chef::HTTP::Decompressor
19
- use Chef::HTTP::Authenticator
20
- end
21
- end