chef-config 12.4.3 → 12.5.0.alpha.0

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: 04318bb1957964ab7a38dc8ef6c700cff7594ddb
4
- data.tar.gz: 7af1c612414e25cd40cd01e0b5ad77d4e764d731
3
+ metadata.gz: 2347fb5ae0e3e633f6147f5dc882b304e151aa95
4
+ data.tar.gz: 08d2e27cff0117c90f66d1480a9c25ecc36b5e34
5
5
  SHA512:
6
- metadata.gz: b1702f92959f4031d59d5f7835025b27309dccf736752b751a9ef509a61116f86e4d3a46d5aebbcd1bd94aea008e810fa50a57a89d07af1892660468a00a658b
7
- data.tar.gz: de1b0c12333199c52de7b306bc7d943dbd7341c6de5c5f55bdbdf4d1f926aebdbbac5f3dd2342a758bf2eaa9a011eb2ace9ec4c960540136661e5d4f3cb3d889
6
+ metadata.gz: 7a3346f2a58de6eb58d17d916b13e590ec863e42d7408de0968d7df5a83e3a3872a507b8387571ee9c8cd52caaa2eabc9b34261dfcc5be27b56a25acaa056646
7
+ data.tar.gz: ba017cd8a5a5ccb7b221f5d352c0b6926aa4a8e21ece21b9b1fa5d9efd595a6c28abf4783157b0e90accd9be0955533b711a98f8e162d669a734c7599a843f0c
@@ -739,6 +739,3 @@ module ChefConfig
739
739
  end
740
740
  end
741
741
  end
742
-
743
-
744
-
@@ -20,7 +20,7 @@ require 'chef-config/logger'
20
20
 
21
21
  module ChefConfig
22
22
 
23
- class InvalidPath < StandardError
24
- end
23
+ class ConfigurationError < ArgumentError; end
24
+ class InvalidPath < StandardError; end
25
25
 
26
26
  end
@@ -20,6 +20,6 @@
20
20
  #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
21
21
 
22
22
  module ChefConfig
23
- VERSION = '12.4.3'
23
+ VERSION = '12.5.0.alpha.0'
24
24
  end
25
25
 
@@ -0,0 +1,179 @@
1
+ #
2
+ # Author:: Daniel DeLeo (<dan@chef.io>)
3
+ # Copyright:: Copyright (c) 2014 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'chef-config/config'
20
+ require 'chef-config/exceptions'
21
+ require 'chef-config/logger'
22
+ require 'chef-config/path_helper'
23
+ require 'chef-config/windows'
24
+
25
+ module ChefConfig
26
+ class WorkstationConfigLoader
27
+
28
+ # Path to a config file requested by user, (e.g., via command line option). Can be nil
29
+ attr_accessor :explicit_config_file
30
+
31
+ # TODO: initialize this with a logger for Chef and Knife
32
+ def initialize(explicit_config_file, logger=nil)
33
+ @explicit_config_file = explicit_config_file
34
+ @chef_config_dir = nil
35
+ @config_location = nil
36
+ @logger = logger || NullLogger.new
37
+ end
38
+
39
+ def no_config_found?
40
+ config_location.nil?
41
+ end
42
+
43
+ def config_location
44
+ @config_location ||= (explicit_config_file || locate_local_config)
45
+ end
46
+
47
+ def chef_config_dir
48
+ if @chef_config_dir.nil?
49
+ @chef_config_dir = false
50
+ full_path = working_directory.split(File::SEPARATOR)
51
+ (full_path.length - 1).downto(0) do |i|
52
+ candidate_directory = File.join(full_path[0..i] + [".chef"])
53
+ if File.exist?(candidate_directory) && File.directory?(candidate_directory)
54
+ @chef_config_dir = candidate_directory
55
+ break
56
+ end
57
+ end
58
+ end
59
+ @chef_config_dir
60
+ end
61
+
62
+ def load
63
+ # Ignore it if there's no explicit_config_file and can't find one at a
64
+ # default path.
65
+ return false if config_location.nil?
66
+
67
+ if explicit_config_file && !path_exists?(config_location)
68
+ raise ChefConfig::ConfigurationError, "Specified config file #{config_location} does not exist"
69
+ end
70
+
71
+ # Have to set Config.config_file b/c other config is derived from it.
72
+ Config.config_file = config_location
73
+ read_config(IO.read(config_location), config_location)
74
+ end
75
+
76
+ # (Private API, public for test purposes)
77
+ def env
78
+ ENV
79
+ end
80
+
81
+ # (Private API, public for test purposes)
82
+ def path_exists?(path)
83
+ Pathname.new(path).expand_path.exist?
84
+ end
85
+
86
+ private
87
+
88
+ def have_config?(path)
89
+ if path_exists?(path)
90
+ logger.info("Using config at #{path}")
91
+ true
92
+ else
93
+ logger.debug("Config not found at #{path}, trying next option")
94
+ false
95
+ end
96
+ end
97
+
98
+ def locate_local_config
99
+ candidate_configs = []
100
+
101
+ # Look for $KNIFE_HOME/knife.rb (allow multiple knives config on same machine)
102
+ if env['KNIFE_HOME']
103
+ candidate_configs << File.join(env['KNIFE_HOME'], 'config.rb')
104
+ candidate_configs << File.join(env['KNIFE_HOME'], 'knife.rb')
105
+ end
106
+ # Look for $PWD/knife.rb
107
+ if Dir.pwd
108
+ candidate_configs << File.join(Dir.pwd, 'config.rb')
109
+ candidate_configs << File.join(Dir.pwd, 'knife.rb')
110
+ end
111
+ # Look for $UPWARD/.chef/knife.rb
112
+ if chef_config_dir
113
+ candidate_configs << File.join(chef_config_dir, 'config.rb')
114
+ candidate_configs << File.join(chef_config_dir, 'knife.rb')
115
+ end
116
+ # Look for $HOME/.chef/knife.rb
117
+ PathHelper.home('.chef') do |dot_chef_dir|
118
+ candidate_configs << File.join(dot_chef_dir, 'config.rb')
119
+ candidate_configs << File.join(dot_chef_dir, 'knife.rb')
120
+ end
121
+
122
+ candidate_configs.find do | candidate_config |
123
+ have_config?(candidate_config)
124
+ end
125
+ end
126
+
127
+ def working_directory
128
+ a = if ChefConfig.windows?
129
+ env['CD']
130
+ else
131
+ env['PWD']
132
+ end || Dir.pwd
133
+
134
+ a
135
+ end
136
+
137
+ def read_config(config_content, config_file_path)
138
+ Config.from_string(config_content, config_file_path)
139
+ rescue SignalException
140
+ raise
141
+ rescue SyntaxError => e
142
+ message = ""
143
+ message << "You have invalid ruby syntax in your config file #{config_file_path}\n\n"
144
+ message << "#{e.class.name}: #{e.message}\n"
145
+ if file_line = e.message[/#{Regexp.escape(config_file_path)}:[\d]+/]
146
+ line = file_line[/:([\d]+)$/, 1].to_i
147
+ message << highlight_config_error(config_file_path, line)
148
+ end
149
+ raise ChefConfig::ConfigurationError, message
150
+ rescue Exception => e
151
+ message = "You have an error in your config file #{config_file_path}\n\n"
152
+ message << "#{e.class.name}: #{e.message}\n"
153
+ filtered_trace = e.backtrace.grep(/#{Regexp.escape(config_file_path)}/)
154
+ filtered_trace.each {|bt_line| message << " " << bt_line << "\n" }
155
+ if !filtered_trace.empty?
156
+ line_nr = filtered_trace.first[/#{Regexp.escape(config_file_path)}:([\d]+)/, 1]
157
+ message << highlight_config_error(config_file_path, line_nr.to_i)
158
+ end
159
+ raise ChefConfig::ConfigurationError, message
160
+ end
161
+
162
+
163
+ def highlight_config_error(file, line)
164
+ config_file_lines = []
165
+ IO.readlines(file).each_with_index {|l, i| config_file_lines << "#{(i + 1).to_s.rjust(3)}: #{l.chomp}"}
166
+ if line == 1
167
+ lines = config_file_lines[0..3]
168
+ else
169
+ lines = config_file_lines[Range.new(line - 2, line)]
170
+ end
171
+ "Relevant file content:\n" + lines.join("\n") + "\n"
172
+ end
173
+
174
+ def logger
175
+ @logger
176
+ end
177
+
178
+ end
179
+ end
@@ -0,0 +1,291 @@
1
+ #
2
+ # Author:: Daniel DeLeo (<dan@getchef.com>)
3
+ # Copyright:: Copyright (c) 2014 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'spec_helper'
20
+ require 'tempfile'
21
+
22
+ require 'chef-config/exceptions'
23
+ require 'chef-config/windows'
24
+ require 'chef-config/workstation_config_loader'
25
+
26
+ RSpec.describe ChefConfig::WorkstationConfigLoader do
27
+
28
+ let(:explicit_config_location) { nil }
29
+
30
+ let(:env) { {} }
31
+
32
+ let(:config_loader) do
33
+ described_class.new(explicit_config_location).tap do |c|
34
+ allow(c).to receive(:env).and_return(env)
35
+ end
36
+ end
37
+
38
+ # Test methods that do I/O or reference external state which are stubbed out
39
+ # elsewhere.
40
+ describe "external dependencies" do
41
+ let(:config_loader) { described_class.new(nil) }
42
+
43
+ it "delegates to ENV for env" do
44
+ expect(config_loader.env).to equal(ENV)
45
+ end
46
+
47
+ it "tests a path's existence" do
48
+ expect(config_loader.path_exists?('/nope/nope/nope/nope/frab/jab/nab')).to be(false)
49
+ expect(config_loader.path_exists?(__FILE__)).to be(true)
50
+ end
51
+
52
+ end
53
+
54
+ describe "locating the config file" do
55
+ context "without an explicit config" do
56
+
57
+ before do
58
+ allow(config_loader).to receive(:path_exists?).with(an_instance_of(String)).and_return(false)
59
+ end
60
+
61
+ it "has no config if HOME is not set" do
62
+ expect(config_loader.config_location).to be(nil)
63
+ expect(config_loader.no_config_found?).to be(true)
64
+ end
65
+
66
+ context "when HOME is set and contains a knife.rb" do
67
+
68
+ let(:home) { "/Users/example.user" }
69
+
70
+ before do
71
+ allow(ChefConfig::PathHelper).to receive(:home).with('.chef').and_yield(File.join(home, '.chef'))
72
+ allow(config_loader).to receive(:path_exists?).with("#{home}/.chef/knife.rb").and_return(true)
73
+ end
74
+
75
+ it "uses the config in HOME/.chef/knife.rb" do
76
+ expect(config_loader.config_location).to eq("#{home}/.chef/knife.rb")
77
+ end
78
+
79
+ context "and has a config.rb" do
80
+
81
+ before do
82
+ allow(config_loader).to receive(:path_exists?).with("#{home}/.chef/config.rb").and_return(true)
83
+ end
84
+
85
+ it "uses the config in HOME/.chef/config.rb" do
86
+ expect(config_loader.config_location).to eq("#{home}/.chef/config.rb")
87
+ end
88
+
89
+ context "and/or a parent dir contains a .chef dir" do
90
+
91
+ let(:env_pwd) { "/path/to/cwd" }
92
+
93
+ before do
94
+ if ChefConfig.windows?
95
+ env["CD"] = env_pwd
96
+ else
97
+ env["PWD"] = env_pwd
98
+ end
99
+
100
+ allow(config_loader).to receive(:path_exists?).with("#{env_pwd}/.chef/knife.rb").and_return(true)
101
+ allow(File).to receive(:exist?).with("#{env_pwd}/.chef").and_return(true)
102
+ allow(File).to receive(:directory?).with("#{env_pwd}/.chef").and_return(true)
103
+ end
104
+
105
+ it "prefers the config from parent_dir/.chef" do
106
+ expect(config_loader.config_location).to eq("#{env_pwd}/.chef/knife.rb")
107
+ end
108
+
109
+ context "and the parent dir's .chef dir has a config.rb" do
110
+
111
+ before do
112
+ allow(config_loader).to receive(:path_exists?).with("#{env_pwd}/.chef/config.rb").and_return(true)
113
+ end
114
+
115
+ it "prefers the config from parent_dir/.chef" do
116
+ expect(config_loader.config_location).to eq("#{env_pwd}/.chef/config.rb")
117
+ end
118
+
119
+ context "and/or the current working directory contains a .chef dir" do
120
+
121
+ let(:cwd) { Dir.pwd }
122
+
123
+ before do
124
+ allow(config_loader).to receive(:path_exists?).with("#{cwd}/knife.rb").and_return(true)
125
+ end
126
+
127
+ it "prefers a knife.rb located in the cwd" do
128
+ expect(config_loader.config_location).to eq("#{cwd}/knife.rb")
129
+ end
130
+
131
+ context "and the CWD's .chef dir has a config.rb" do
132
+
133
+ before do
134
+ allow(config_loader).to receive(:path_exists?).with("#{cwd}/config.rb").and_return(true)
135
+ end
136
+
137
+ it "prefers a config located in the cwd" do
138
+ expect(config_loader.config_location).to eq("#{cwd}/config.rb")
139
+ end
140
+
141
+
142
+ context "and/or KNIFE_HOME is set" do
143
+
144
+ let(:knife_home) { "/path/to/knife/home" }
145
+
146
+ before do
147
+ env["KNIFE_HOME"] = knife_home
148
+ allow(config_loader).to receive(:path_exists?).with("#{knife_home}/knife.rb").and_return(true)
149
+ end
150
+
151
+ it "prefers a knife located in KNIFE_HOME" do
152
+ expect(config_loader.config_location).to eq("/path/to/knife/home/knife.rb")
153
+ end
154
+
155
+ context "and KNIFE_HOME contains a config.rb" do
156
+
157
+ before do
158
+ env["KNIFE_HOME"] = knife_home
159
+ allow(config_loader).to receive(:path_exists?).with("#{knife_home}/config.rb").and_return(true)
160
+ end
161
+
162
+ it "prefers a config.rb located in KNIFE_HOME" do
163
+ expect(config_loader.config_location).to eq("/path/to/knife/home/config.rb")
164
+ end
165
+
166
+ end
167
+
168
+ end
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
175
+
176
+ context "when the current working dir is inside a symlinked directory" do
177
+ before do
178
+ # pwd according to your shell is /home/someuser/prod/chef-repo, but
179
+ # chef-repo is a symlink to /home/someuser/codes/chef-repo
180
+ env["CD"] = "/home/someuser/prod/chef-repo" # windows
181
+ env["PWD"] = "/home/someuser/prod/chef-repo" # unix
182
+
183
+ allow(Dir).to receive(:pwd).and_return("/home/someuser/codes/chef-repo")
184
+ end
185
+
186
+ it "loads the config from the non-dereferenced directory path" do
187
+ expect(File).to receive(:exist?).with("/home/someuser/prod/chef-repo/.chef").and_return(false)
188
+ expect(File).to receive(:exist?).with("/home/someuser/prod/.chef").and_return(true)
189
+ expect(File).to receive(:directory?).with("/home/someuser/prod/.chef").and_return(true)
190
+
191
+ expect(config_loader).to receive(:path_exists?).with("/home/someuser/prod/.chef/knife.rb").and_return(true)
192
+
193
+ expect(config_loader.config_location).to eq("/home/someuser/prod/.chef/knife.rb")
194
+ end
195
+ end
196
+ end
197
+
198
+ context "when given an explicit config to load" do
199
+
200
+ let(:explicit_config_location) { "/path/to/explicit/config.rb" }
201
+
202
+ it "prefers the explicit config" do
203
+ expect(config_loader.config_location).to eq(explicit_config_location)
204
+ end
205
+
206
+ end
207
+ end
208
+
209
+
210
+ describe "loading the config file" do
211
+
212
+ context "when no explicit config is specifed and no implicit config is found" do
213
+
214
+ before do
215
+ allow(config_loader).to receive(:path_exists?).with(an_instance_of(String)).and_return(false)
216
+ end
217
+
218
+ it "skips loading" do
219
+ expect(config_loader.config_location).to be(nil)
220
+ expect(config_loader.load).to be(false)
221
+ end
222
+
223
+ end
224
+
225
+ context "when an explicit config is given but it doesn't exist" do
226
+
227
+ let(:explicit_config_location) { "/nope/nope/nope/frab/jab/nab" }
228
+
229
+ it "raises a configuration error" do
230
+ expect { config_loader.load }.to raise_error(ChefConfig::ConfigurationError)
231
+ end
232
+
233
+ end
234
+
235
+ context "when the config file exists" do
236
+
237
+ let(:config_content) { "" }
238
+
239
+ # We need to keep a reference to the tempfile because while #close does
240
+ # not unlink the file, the object being GC'd will.
241
+ let(:tempfile) do
242
+ Tempfile.new("Chef-WorkstationConfigLoader-rspec-test").tap do |t|
243
+ t.print(config_content)
244
+ t.close
245
+ end
246
+ end
247
+
248
+ let(:explicit_config_location) do
249
+ tempfile.path
250
+ end
251
+
252
+ after { File.unlink(explicit_config_location) if File.exist?(explicit_config_location) }
253
+
254
+ context "and is valid" do
255
+
256
+ let(:config_content) { "config_file_evaluated(true)" }
257
+
258
+ it "loads the config" do
259
+ expect(config_loader.load).to be(true)
260
+ expect(ChefConfig::Config.config_file_evaluated).to be(true)
261
+ end
262
+
263
+ it "sets ChefConfig::Config.config_file" do
264
+ config_loader.load
265
+ expect(ChefConfig::Config.config_file).to eq(explicit_config_location)
266
+ end
267
+ end
268
+
269
+ context "and has a syntax error" do
270
+
271
+ let(:config_content) { "{{{{{:{{" }
272
+
273
+ it "raises a ConfigurationError" do
274
+ expect { config_loader.load }.to raise_error(ChefConfig::ConfigurationError)
275
+ end
276
+ end
277
+
278
+ context "and raises a ruby exception during evaluation" do
279
+
280
+ let(:config_content) { ":foo\n:bar\nraise 'oops'\n:baz\n" }
281
+
282
+ it "raises a ConfigurationError" do
283
+ expect { config_loader.load }.to raise_error(ChefConfig::ConfigurationError)
284
+ end
285
+ end
286
+
287
+ end
288
+
289
+ end
290
+
291
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-config
3
3
  version: !ruby/object:Gem::Version
4
- version: 12.4.3
4
+ version: 12.5.0.alpha.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Jacob
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-23 00:00:00.000000000 Z
11
+ date: 2015-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mixlib-shellout
@@ -111,9 +111,11 @@ files:
111
111
  - lib/chef-config/path_helper.rb
112
112
  - lib/chef-config/version.rb
113
113
  - lib/chef-config/windows.rb
114
+ - lib/chef-config/workstation_config_loader.rb
114
115
  - spec/spec_helper.rb
115
116
  - spec/unit/config_spec.rb
116
117
  - spec/unit/path_helper_spec.rb
118
+ - spec/unit/workstation_config_loader_spec.rb
117
119
  homepage: https://github.com/chef/chef
118
120
  licenses:
119
121
  - Apache-2.0
@@ -129,12 +131,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
129
131
  version: '0'
130
132
  required_rubygems_version: !ruby/object:Gem::Requirement
131
133
  requirements:
132
- - - ">="
134
+ - - ">"
133
135
  - !ruby/object:Gem::Version
134
- version: '0'
136
+ version: 1.3.1
135
137
  requirements: []
136
138
  rubyforge_project:
137
- rubygems_version: 2.4.5
139
+ rubygems_version: 2.4.4
138
140
  signing_key:
139
141
  specification_version: 4
140
142
  summary: Chef's default configuration and config loading