cheffish 0.4.1 → 0.5.beta

Sign up to get free protection for your applications and to get access to all the features.
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