chef-config 16.3.45 → 16.5.77
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 +4 -4
- data/lib/chef-config/config.rb +78 -50
- data/lib/chef-config/mixin/credentials.rb +8 -7
- data/lib/chef-config/mixin/train_transport.rb +141 -0
- data/lib/chef-config/path_helper.rb +74 -44
- data/lib/chef-config/version.rb +1 -1
- data/lib/chef-config/workstation_config_loader.rb +9 -11
- data/spec/unit/config_spec.rb +64 -7
- data/spec/unit/fips_spec.rb +1 -1
- data/spec/unit/path_helper_spec.rb +103 -38
- data/spec/unit/workstation_config_loader_spec.rb +1 -1
- metadata +5 -5
- data/lib/chef-config/dist.rb +0 -26
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: be09ac190045e0d04778b9d2121594585ab1e56bb6581ff0dfe5ff1591764141
|
|
4
|
+
data.tar.gz: 77fad1d3fb02f4de4e8442bfa0feea9c5afc659e289541e1984cc244f4cf6794
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e507e5b152b916aa72aac2ce937daab4af31c356cbb9f83a7eaf71f9a1a3df9ba7f473990617983b5277a8351729432d41121094d4b0da524933230c92d80f24
|
|
7
|
+
data.tar.gz: ec00b7ea3951fa346a0d97123e06edb3b724322558085bd263817412c0fa3f3556a97c593529c23964dc48843316392768a7e9c58554e3394e7913eb517e0ac2
|
data/lib/chef-config/config.rb
CHANGED
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
# limitations under the License.
|
|
21
21
|
|
|
22
22
|
require "mixlib/config" unless defined?(Mixlib::Config)
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
autoload :Pathname, "pathname"
|
|
24
|
+
autoload :ChefUtils, "chef-utils"
|
|
25
25
|
|
|
26
26
|
require_relative "fips"
|
|
27
27
|
require_relative "logger"
|
|
@@ -29,12 +29,16 @@ require_relative "windows"
|
|
|
29
29
|
require_relative "path_helper"
|
|
30
30
|
require_relative "mixin/fuzzy_hostname_matcher"
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
module Mixlib
|
|
33
|
+
autoload :ShellOut, "mixlib/shellout"
|
|
34
|
+
end
|
|
35
|
+
autoload :URI, "uri"
|
|
36
|
+
module Addressable
|
|
37
|
+
autoload :URI, "addressable/uri"
|
|
38
|
+
end
|
|
39
|
+
autoload :OpenSSL, "openssl"
|
|
40
|
+
autoload :YAML, "yaml"
|
|
41
|
+
require "chef-utils/dist" unless defined?(ChefUtils::Dist)
|
|
38
42
|
|
|
39
43
|
module ChefConfig
|
|
40
44
|
|
|
@@ -74,42 +78,66 @@ module ChefConfig
|
|
|
74
78
|
path
|
|
75
79
|
end
|
|
76
80
|
|
|
77
|
-
# On *nix, /etc/chef
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
+
# On *nix, /etc/chef, on Windows C:\chef
|
|
82
|
+
#
|
|
83
|
+
# @param windows [Boolean] optional flag to force to windows or unix-style
|
|
84
|
+
# @return [String] the platform-specific path
|
|
85
|
+
#
|
|
86
|
+
def self.etc_chef_dir(windows: ChefUtils.windows?)
|
|
87
|
+
path = windows ? c_chef_dir : PathHelper.join("/etc", ChefUtils::Dist::Infra::DIR_SUFFIX, windows: windows)
|
|
88
|
+
PathHelper.cleanpath(path, windows: windows)
|
|
81
89
|
end
|
|
82
90
|
|
|
83
|
-
# On *nix, /var/chef
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
91
|
+
# On *nix, /var/chef, on Windows C:\chef
|
|
92
|
+
#
|
|
93
|
+
# @param windows [Boolean] optional flag to force to windows or unix-style
|
|
94
|
+
# @return [String] the platform-specific path
|
|
95
|
+
#
|
|
96
|
+
def self.var_chef_dir(windows: ChefUtils.windows?)
|
|
97
|
+
path = windows ? c_chef_dir : PathHelper.join("/var", ChefUtils::Dist::Infra::DIR_SUFFIX, windows: windows)
|
|
98
|
+
PathHelper.cleanpath(path, windows: windows)
|
|
87
99
|
end
|
|
88
100
|
|
|
89
|
-
# On *nix,
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
101
|
+
# On *nix, /var, on Windows C:\
|
|
102
|
+
#
|
|
103
|
+
# @param windows [Boolean] optional flag to force to windows or unix-style
|
|
104
|
+
# @return [String] the platform-specific path
|
|
105
|
+
#
|
|
106
|
+
def self.var_root_dir(windows: ChefUtils.windows?)
|
|
107
|
+
path = windows ? "C:\\" : "/var"
|
|
108
|
+
PathHelper.cleanpath(path, windows: windows)
|
|
93
109
|
end
|
|
94
110
|
|
|
95
111
|
# On windows, C:/chef/
|
|
96
|
-
|
|
112
|
+
#
|
|
113
|
+
# (should only be called in a windows-context)
|
|
114
|
+
#
|
|
115
|
+
# @return [String] the platform-specific path
|
|
116
|
+
#
|
|
117
|
+
def self.c_chef_dir(windows: ChefUtils.windows?)
|
|
97
118
|
drive = windows_installation_drive || "C:"
|
|
98
|
-
|
|
99
|
-
PathHelper.cleanpath(path)
|
|
119
|
+
PathHelper.join(drive, ChefUtils::Dist::Infra::DIR_SUFFIX, windows: windows)
|
|
100
120
|
end
|
|
101
121
|
|
|
102
|
-
|
|
122
|
+
# On windows, C:/opscode
|
|
123
|
+
#
|
|
124
|
+
# (should only be called in a windows-context)
|
|
125
|
+
#
|
|
126
|
+
# @return [String] the platform-specific path
|
|
127
|
+
#
|
|
128
|
+
def self.c_opscode_dir(windows: ChefUtils.windows?)
|
|
103
129
|
drive = windows_installation_drive || "C:"
|
|
104
|
-
|
|
105
|
-
PathHelper.cleanpath(path)
|
|
130
|
+
PathHelper.join(drive, ChefUtils::Dist::Org::LEGACY_CONF_DIR, ChefUtils::Dist::Infra::DIR_SUFFIX, windows: windows)
|
|
106
131
|
end
|
|
107
132
|
|
|
108
133
|
# the drive where Chef is installed on a windows host. This is determined
|
|
109
134
|
# either by the drive containing the current file or by the SYSTEMDRIVE ENV
|
|
110
135
|
# variable
|
|
111
136
|
#
|
|
137
|
+
# (should only be called in a windows-context)
|
|
138
|
+
#
|
|
112
139
|
# @return [String] the drive letter
|
|
140
|
+
#
|
|
113
141
|
def self.windows_installation_drive
|
|
114
142
|
if ChefUtils.windows?
|
|
115
143
|
drive = File.expand_path(__FILE__).split("/", 2)[0]
|
|
@@ -164,7 +192,7 @@ module ChefConfig
|
|
|
164
192
|
if config_file
|
|
165
193
|
PathHelper.dirname(PathHelper.canonical_path(config_file, false))
|
|
166
194
|
else
|
|
167
|
-
PathHelper.join(PathHelper.cleanpath(user_home),
|
|
195
|
+
PathHelper.join(PathHelper.cleanpath(user_home), ChefUtils::Dist::Infra::USER_CONF_DIR, "")
|
|
168
196
|
end
|
|
169
197
|
end
|
|
170
198
|
|
|
@@ -243,7 +271,7 @@ module ChefConfig
|
|
|
243
271
|
end
|
|
244
272
|
path = new_path
|
|
245
273
|
end
|
|
246
|
-
ChefConfig.logger.info("Auto-discovered #{
|
|
274
|
+
ChefConfig.logger.info("Auto-discovered #{ChefUtils::Dist::Infra::SHORT} repository at #{path}")
|
|
247
275
|
path
|
|
248
276
|
end
|
|
249
277
|
|
|
@@ -341,12 +369,12 @@ module ChefConfig
|
|
|
341
369
|
# Otherwise, we'll create .chef under the user's home directory and use that as
|
|
342
370
|
# the cache path.
|
|
343
371
|
unless path_accessible?(primary_cache_path) || path_accessible?(primary_cache_root)
|
|
344
|
-
secondary_cache_path = PathHelper.join(user_home,
|
|
345
|
-
secondary_cache_path = target_mode? ?
|
|
372
|
+
secondary_cache_path = PathHelper.join(user_home, ChefUtils::Dist::Infra::USER_CONF_DIR)
|
|
373
|
+
secondary_cache_path = target_mode? ? PathHelper.join(secondary_cache_path, target_mode.host) : secondary_cache_path
|
|
346
374
|
ChefConfig.logger.trace("Unable to access cache at #{primary_cache_path}. Switching cache to #{secondary_cache_path}")
|
|
347
375
|
secondary_cache_path
|
|
348
376
|
else
|
|
349
|
-
target_mode? ?
|
|
377
|
+
target_mode? ? PathHelper.join(primary_cache_path, target_mode.host) : primary_cache_path
|
|
350
378
|
end
|
|
351
379
|
end
|
|
352
380
|
end
|
|
@@ -355,7 +383,7 @@ module ChefConfig
|
|
|
355
383
|
#
|
|
356
384
|
# @param path [String]
|
|
357
385
|
def self.path_accessible?(path)
|
|
358
|
-
File.
|
|
386
|
+
File.exist?(path) && File.readable?(path) && File.writable?(path)
|
|
359
387
|
end
|
|
360
388
|
|
|
361
389
|
# Where cookbook files are stored on the server (by content checksum)
|
|
@@ -372,7 +400,7 @@ module ChefConfig
|
|
|
372
400
|
# If your `file_cache_path` resides on a NFS (or non-flock()-supporting
|
|
373
401
|
# fs), it's recommended to set this to something like
|
|
374
402
|
# '/tmp/chef-client-running.pid'
|
|
375
|
-
default(:lockfile) { PathHelper.join(file_cache_path, "#{
|
|
403
|
+
default(:lockfile) { PathHelper.join(file_cache_path, "#{ChefUtils::Dist::Infra::CLIENT}-running.pid") }
|
|
376
404
|
|
|
377
405
|
## Daemonization Settings ##
|
|
378
406
|
# What user should Chef run as?
|
|
@@ -621,7 +649,7 @@ module ChefConfig
|
|
|
621
649
|
# credentials toml files which doesn't allow ruby symbol values
|
|
622
650
|
configurable(:ssl_verify_mode).writes_value do |value|
|
|
623
651
|
if value.is_a?(String) && value[0] == ":"
|
|
624
|
-
value[1
|
|
652
|
+
value[1..].to_sym
|
|
625
653
|
else
|
|
626
654
|
value.to_sym
|
|
627
655
|
end
|
|
@@ -769,7 +797,7 @@ module ChefConfig
|
|
|
769
797
|
if chef_server_url.to_s =~ %r{/organizations/(.*)$}
|
|
770
798
|
"#{$1}-validator"
|
|
771
799
|
else
|
|
772
|
-
"#{
|
|
800
|
+
"#{ChefUtils::Dist::Infra::SHORT}-validator"
|
|
773
801
|
end
|
|
774
802
|
end
|
|
775
803
|
|
|
@@ -843,7 +871,7 @@ module ChefConfig
|
|
|
843
871
|
default :profile, nil
|
|
844
872
|
|
|
845
873
|
default :chef_guid_path do
|
|
846
|
-
PathHelper.join(config_dir, "#{
|
|
874
|
+
PathHelper.join(config_dir, "#{ChefUtils::Dist::Infra::SHORT}_guid")
|
|
847
875
|
end
|
|
848
876
|
|
|
849
877
|
default :chef_guid, nil
|
|
@@ -1052,7 +1080,7 @@ module ChefConfig
|
|
|
1052
1080
|
# generated by the DataCollector when Chef is run in Solo mode. This
|
|
1053
1081
|
# allows users to associate their Solo nodes with faux organizations
|
|
1054
1082
|
# without the nodes being connected to an actual Chef Server.
|
|
1055
|
-
default :organization, "#{
|
|
1083
|
+
default :organization, "#{ChefUtils::Dist::Infra::SHORT}_solo"
|
|
1056
1084
|
end
|
|
1057
1085
|
|
|
1058
1086
|
configurable(:http_proxy)
|
|
@@ -1078,13 +1106,6 @@ module ChefConfig
|
|
|
1078
1106
|
export_no_proxy(no_proxy) if key?(:no_proxy) && no_proxy
|
|
1079
1107
|
end
|
|
1080
1108
|
|
|
1081
|
-
# Character classes for Addressable
|
|
1082
|
-
# See https://www.ietf.org/rfc/rfc3986.txt 3.2.1
|
|
1083
|
-
# The user part may not have a : in it
|
|
1084
|
-
USER = Addressable::URI::CharacterClasses::UNRESERVED + Addressable::URI::CharacterClasses::SUB_DELIMS
|
|
1085
|
-
# The password part may have any valid USERINFO characters
|
|
1086
|
-
PASSWORD = USER + "\\:"
|
|
1087
|
-
|
|
1088
1109
|
# Builds a proxy uri and exports it to the appropriate environment variables. Examples:
|
|
1089
1110
|
# http://username:password@hostname:port
|
|
1090
1111
|
# https://username@hostname:port
|
|
@@ -1096,15 +1117,22 @@ module ChefConfig
|
|
|
1096
1117
|
# pass = password
|
|
1097
1118
|
# @api private
|
|
1098
1119
|
def self.export_proxy(scheme, path, user, pass)
|
|
1120
|
+
# Character classes for Addressable
|
|
1121
|
+
# See https://www.ietf.org/rfc/rfc3986.txt 3.2.1
|
|
1122
|
+
# The user part may not have a : in it
|
|
1123
|
+
user_class = Addressable::URI::CharacterClasses::UNRESERVED + Addressable::URI::CharacterClasses::SUB_DELIMS
|
|
1124
|
+
# The password part may have any valid USERINFO characters
|
|
1125
|
+
password_class = user_class + "\\:"
|
|
1126
|
+
|
|
1099
1127
|
path = "#{scheme}://#{path}" unless path.include?("://")
|
|
1100
1128
|
# URI.split returns the following parts:
|
|
1101
1129
|
# [scheme, userinfo, host, port, registry, path, opaque, query, fragment]
|
|
1102
1130
|
uri = Addressable::URI.encode(path, Addressable::URI)
|
|
1103
1131
|
|
|
1104
1132
|
if user && !user.empty?
|
|
1105
|
-
userinfo = Addressable::URI.encode_component(user,
|
|
1133
|
+
userinfo = Addressable::URI.encode_component(user, user_class)
|
|
1106
1134
|
if pass
|
|
1107
|
-
userinfo << ":#{Addressable::URI.encode_component(pass,
|
|
1135
|
+
userinfo << ":#{Addressable::URI.encode_component(pass, password_class)}"
|
|
1108
1136
|
end
|
|
1109
1137
|
uri.userinfo = userinfo
|
|
1110
1138
|
end
|
|
@@ -1179,7 +1207,7 @@ module ChefConfig
|
|
|
1179
1207
|
# Transform into the form en_ZZ.UTF-8
|
|
1180
1208
|
guessed_locale.gsub(/UTF-?8$/i, "UTF-8")
|
|
1181
1209
|
else
|
|
1182
|
-
ChefConfig.logger.warn "Please install an English UTF-8 locale for
|
|
1210
|
+
ChefConfig.logger.warn "Please install an English UTF-8 locale for #{ChefUtils::Dist::Infra::PRODUCT} to use, falling back to C locale and disabling UTF-8 support."
|
|
1183
1211
|
"C"
|
|
1184
1212
|
end
|
|
1185
1213
|
end
|
|
@@ -1232,9 +1260,9 @@ module ChefConfig
|
|
|
1232
1260
|
# @api private
|
|
1233
1261
|
def self.enable_fips_mode
|
|
1234
1262
|
OpenSSL.fips_mode = true
|
|
1235
|
-
require "digest"
|
|
1236
|
-
require "digest/sha1"
|
|
1237
|
-
require "digest/md5"
|
|
1263
|
+
require "digest" unless defined?(Digest)
|
|
1264
|
+
require "digest/sha1" unless defined?(Digest::SHA1)
|
|
1265
|
+
require "digest/md5" unless defined?(Digest::MD5)
|
|
1238
1266
|
# Remove pre-existing constants if they do exist to reduce the
|
|
1239
1267
|
# amount of log spam and warnings.
|
|
1240
1268
|
Digest.send(:remove_const, "SHA1") if Digest.const_defined?("SHA1")
|
|
@@ -15,8 +15,9 @@
|
|
|
15
15
|
# limitations under the License.
|
|
16
16
|
#
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
autoload :Tomlrb, "tomlrb"
|
|
19
19
|
require_relative "../path_helper"
|
|
20
|
+
require "chef-utils/dist" unless defined?(ChefUtils::Dist)
|
|
20
21
|
|
|
21
22
|
module ChefConfig
|
|
22
23
|
module Mixin
|
|
@@ -36,7 +37,7 @@ module ChefConfig
|
|
|
36
37
|
# normally set via a command-line option.
|
|
37
38
|
# @return [String]
|
|
38
39
|
def credentials_profile(profile = nil)
|
|
39
|
-
context_file = PathHelper.home(
|
|
40
|
+
context_file = PathHelper.home(ChefUtils::Dist::Infra::USER_CONF_DIR, "context").freeze
|
|
40
41
|
if !profile.nil?
|
|
41
42
|
profile
|
|
42
43
|
elsif ENV.include?("CHEF_PROFILE")
|
|
@@ -53,7 +54,7 @@ module ChefConfig
|
|
|
53
54
|
# @since 14.4
|
|
54
55
|
# @return [String]
|
|
55
56
|
def credentials_file_path
|
|
56
|
-
PathHelper.home(
|
|
57
|
+
PathHelper.home(ChefUtils::Dist::Infra::USER_CONF_DIR, "credentials").freeze
|
|
57
58
|
end
|
|
58
59
|
|
|
59
60
|
# Load and parse the credentials file.
|
|
@@ -84,17 +85,17 @@ module ChefConfig
|
|
|
84
85
|
# @return [void]
|
|
85
86
|
def load_credentials(profile = nil)
|
|
86
87
|
profile = credentials_profile(profile)
|
|
87
|
-
|
|
88
|
-
return if
|
|
88
|
+
cred_config = parse_credentials_file
|
|
89
|
+
return if cred_config.nil? # No credentials, nothing to do here.
|
|
89
90
|
|
|
90
|
-
if
|
|
91
|
+
if cred_config[profile].nil?
|
|
91
92
|
# Unknown profile name. For "default" just silently ignore, otherwise
|
|
92
93
|
# raise an error.
|
|
93
94
|
return if profile == "default"
|
|
94
95
|
|
|
95
96
|
raise ChefConfig::ConfigurationError, "Profile #{profile} doesn't exist. Please add it to #{credentials_file_path}."
|
|
96
97
|
end
|
|
97
|
-
apply_credentials(
|
|
98
|
+
apply_credentials(cred_config[profile], profile)
|
|
98
99
|
end
|
|
99
100
|
end
|
|
100
101
|
end
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Author:: Bryan McLellan <btm@loftninjas.org>
|
|
2
|
+
# Copyright:: Copyright (c) Chef Software Inc.
|
|
3
|
+
# License:: Apache License, Version 2.0
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
#
|
|
17
|
+
|
|
18
|
+
require_relative "credentials"
|
|
19
|
+
autoload :Train, "train"
|
|
20
|
+
require_relative "../config"
|
|
21
|
+
require "chef-utils/dist" unless defined?(ChefUtils::Dist)
|
|
22
|
+
|
|
23
|
+
module ChefConfig
|
|
24
|
+
module Mixin
|
|
25
|
+
module TrainTransport
|
|
26
|
+
include ChefConfig::Mixin::Credentials
|
|
27
|
+
|
|
28
|
+
attr_accessor :logger
|
|
29
|
+
|
|
30
|
+
def initialize(logger)
|
|
31
|
+
@logger = logger
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
#
|
|
35
|
+
# Returns a RFC099 credentials profile as a hash
|
|
36
|
+
#
|
|
37
|
+
def load_credentials(profile)
|
|
38
|
+
# Tomlrb.load_file returns a hash with keys as strings
|
|
39
|
+
credentials = parse_credentials_file
|
|
40
|
+
if contains_split_fqdn?(credentials, profile)
|
|
41
|
+
logger.warn("Credentials file #{credentials_file_path} contains target '#{profile}' as a Hash, expected a string.")
|
|
42
|
+
logger.warn("Hostnames must be surrounded by single quotes, e.g. ['host.example.org']")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# host names must be specified in credentials file as ['foo.example.org'] with quotes
|
|
46
|
+
if !credentials.nil? && !credentials[profile].nil?
|
|
47
|
+
credentials[profile].transform_keys(&:to_sym) # return symbolized keys to match Train.options()
|
|
48
|
+
else
|
|
49
|
+
nil
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Toml creates hashes when a key is separated by periods, e.g.
|
|
54
|
+
# [host.example.org] => { host: { example: { org: {} } } }
|
|
55
|
+
#
|
|
56
|
+
# Returns true if the above example is true
|
|
57
|
+
#
|
|
58
|
+
# A hostname has to be specified as ['host.example.org']
|
|
59
|
+
# This will be a common mistake so we should catch it
|
|
60
|
+
#
|
|
61
|
+
def contains_split_fqdn?(hash, fqdn)
|
|
62
|
+
fqdn.split(".").reduce(hash) do |h, k|
|
|
63
|
+
v = h[k]
|
|
64
|
+
if Hash === v
|
|
65
|
+
v
|
|
66
|
+
else
|
|
67
|
+
break false
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# ChefConfig::Mixin::Credentials.credentials_file_path is designed around knife,
|
|
73
|
+
# overriding it here.
|
|
74
|
+
#
|
|
75
|
+
# Credentials file preference:
|
|
76
|
+
#
|
|
77
|
+
# 1) target_mode.credentials_file
|
|
78
|
+
# 2) /etc/chef/TARGET_MODE_HOST/credentials
|
|
79
|
+
# 3) #credentials_file_path from parent ($HOME/.chef/credentials)
|
|
80
|
+
#
|
|
81
|
+
def credentials_file_path
|
|
82
|
+
tm_config = config.target_mode
|
|
83
|
+
profile = tm_config.host
|
|
84
|
+
|
|
85
|
+
credentials_file =
|
|
86
|
+
if tm_config.credentials_file && File.exist?(tm_config.credentials_file)
|
|
87
|
+
tm_config.credentials_file
|
|
88
|
+
elsif File.exist?(config.platform_specific_path("#{ChefConfig::Config.etc_chef_dir}/#{profile}/credentials"))
|
|
89
|
+
config.platform_specific_path("#{ChefConfig::Config.etc_chef_dir}/#{profile}/credentials")
|
|
90
|
+
else
|
|
91
|
+
super
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
raise ArgumentError, "No credentials file found for target '#{profile}'" unless credentials_file
|
|
95
|
+
raise ArgumentError, "Credentials file specified for target mode does not exist: '#{credentials_file}'" unless File.exist?(credentials_file)
|
|
96
|
+
|
|
97
|
+
logger.debug("Loading credentials file '#{credentials_file}' for target '#{profile}'")
|
|
98
|
+
|
|
99
|
+
credentials_file
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def build_transport
|
|
103
|
+
return nil unless config.target_mode?
|
|
104
|
+
|
|
105
|
+
# TODO: Consider supporting parsing the protocol from a URI passed to `--target`
|
|
106
|
+
#
|
|
107
|
+
train_config = {}
|
|
108
|
+
|
|
109
|
+
# Load the target_mode config context from config, and place any valid settings into the train configuration
|
|
110
|
+
tm_config = config.target_mode
|
|
111
|
+
protocol = tm_config.protocol
|
|
112
|
+
train_config = tm_config.to_hash.select { |k| Train.options(protocol).key?(k) }
|
|
113
|
+
logger.trace("Using target mode options from #{ChefUtils::Dist::Infra::PRODUCT} config file: #{train_config.keys.join(", ")}") if train_config
|
|
114
|
+
|
|
115
|
+
# Load the credentials file, and place any valid settings into the train configuration
|
|
116
|
+
credentials = load_credentials(tm_config.host)
|
|
117
|
+
if credentials
|
|
118
|
+
valid_settings = credentials.select { |k| Train.options(protocol).key?(k) }
|
|
119
|
+
valid_settings[:enable_password] = credentials[:enable_password] if credentials.key?(:enable_password)
|
|
120
|
+
train_config.merge!(valid_settings)
|
|
121
|
+
logger.trace("Using target mode options from credentials file: #{valid_settings.keys.join(", ")}") if valid_settings
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
train_config[:logger] = logger
|
|
125
|
+
|
|
126
|
+
# Train handles connection retries for us
|
|
127
|
+
Train.create(protocol, train_config)
|
|
128
|
+
rescue SocketError => e # likely a dns failure, not caught by train
|
|
129
|
+
e.message.replace "Error connecting to #{train_config[:target]} - #{e.message}"
|
|
130
|
+
raise e
|
|
131
|
+
rescue Train::PluginLoadError
|
|
132
|
+
logger.error("Invalid target mode protocol: #{protocol}")
|
|
133
|
+
exit(1)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def config
|
|
137
|
+
raise NotImplementedError
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
@@ -26,14 +26,14 @@ module ChefConfig
|
|
|
26
26
|
# Maximum characters in a standard Windows path (260 including drive letter and NUL)
|
|
27
27
|
WIN_MAX_PATH = 259
|
|
28
28
|
|
|
29
|
-
def self.dirname(path)
|
|
30
|
-
if
|
|
29
|
+
def self.dirname(path, windows: ChefUtils.windows?)
|
|
30
|
+
if windows
|
|
31
31
|
# Find the first slash, not counting trailing slashes
|
|
32
32
|
end_slash = path.size
|
|
33
33
|
loop do
|
|
34
|
-
slash = path.rindex(/[#{Regexp.escape(File::SEPARATOR)}#{Regexp.escape(path_separator)}]/, end_slash - 1)
|
|
34
|
+
slash = path.rindex(/[#{Regexp.escape(File::SEPARATOR)}#{Regexp.escape(path_separator(windows: windows))}]/, end_slash - 1)
|
|
35
35
|
if !slash
|
|
36
|
-
return end_slash == path.size ? "." : path_separator
|
|
36
|
+
return end_slash == path.size ? "." : path_separator(windows: windows)
|
|
37
37
|
elsif slash == end_slash - 1
|
|
38
38
|
end_slash = slash
|
|
39
39
|
else
|
|
@@ -47,29 +47,28 @@ module ChefConfig
|
|
|
47
47
|
|
|
48
48
|
BACKSLASH = '\\'.freeze
|
|
49
49
|
|
|
50
|
-
def self.path_separator
|
|
51
|
-
if
|
|
52
|
-
|
|
50
|
+
def self.path_separator(windows: ChefUtils.windows?)
|
|
51
|
+
if windows
|
|
52
|
+
BACKSLASH
|
|
53
53
|
else
|
|
54
54
|
File::SEPARATOR
|
|
55
55
|
end
|
|
56
56
|
end
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
def self.join(*args, windows: ChefUtils.windows?)
|
|
59
|
+
path_separator_regex = Regexp.escape(windows ? "#{File::SEPARATOR}#{BACKSLASH}" : File::SEPARATOR)
|
|
60
|
+
trailing_slashes_regex = /[#{path_separator_regex}]+$/.freeze
|
|
61
|
+
leading_slashes_regex = /^[#{path_separator_regex}]+/.freeze
|
|
59
62
|
|
|
60
|
-
TRAILING_SLASHES_REGEX = /[#{path_separator_regex}]+$/.freeze
|
|
61
|
-
LEADING_SLASHES_REGEX = /^[#{path_separator_regex}]+/.freeze
|
|
62
|
-
|
|
63
|
-
def self.join(*args)
|
|
64
63
|
args.flatten.inject do |joined_path, component|
|
|
65
|
-
joined_path = joined_path.sub(
|
|
66
|
-
component = component.sub(
|
|
67
|
-
joined_path + "#{path_separator}#{component}"
|
|
64
|
+
joined_path = joined_path.sub(trailing_slashes_regex, "")
|
|
65
|
+
component = component.sub(leading_slashes_regex, "")
|
|
66
|
+
joined_path + "#{path_separator(windows: windows)}#{component}"
|
|
68
67
|
end
|
|
69
68
|
end
|
|
70
69
|
|
|
71
|
-
def self.validate_path(path)
|
|
72
|
-
if
|
|
70
|
+
def self.validate_path(path, windows: ChefUtils.windows?)
|
|
71
|
+
if windows
|
|
73
72
|
unless printable?(path)
|
|
74
73
|
msg = "Path '#{path}' contains non-printable characters. Check that backslashes are escaped with another backslash (e.g. C:\\\\Windows) in double-quoted strings."
|
|
75
74
|
ChefConfig.logger.error(msg)
|
|
@@ -108,14 +107,14 @@ module ChefConfig
|
|
|
108
107
|
end
|
|
109
108
|
|
|
110
109
|
# Produces a comparable path.
|
|
111
|
-
def self.canonical_path(path, add_prefix = true)
|
|
110
|
+
def self.canonical_path(path, add_prefix = true, windows: ChefUtils.windows?)
|
|
112
111
|
# First remove extra separators and resolve any relative paths
|
|
113
112
|
abs_path = File.absolute_path(path)
|
|
114
113
|
|
|
115
|
-
if
|
|
114
|
+
if windows
|
|
116
115
|
# Add the \\?\ API prefix on Windows unless add_prefix is false
|
|
117
116
|
# Downcase on Windows where paths are still case-insensitive
|
|
118
|
-
abs_path.gsub!(::File::SEPARATOR, path_separator)
|
|
117
|
+
abs_path.gsub!(::File::SEPARATOR, path_separator(windows: windows))
|
|
119
118
|
if add_prefix && abs_path !~ /^\\\\?\\/
|
|
120
119
|
abs_path.insert(0, "\\\\?\\")
|
|
121
120
|
end
|
|
@@ -126,36 +125,67 @@ module ChefConfig
|
|
|
126
125
|
abs_path
|
|
127
126
|
end
|
|
128
127
|
|
|
129
|
-
#
|
|
130
|
-
#
|
|
131
|
-
#
|
|
132
|
-
#
|
|
133
|
-
# to the user
|
|
134
|
-
#
|
|
135
|
-
#
|
|
136
|
-
#
|
|
128
|
+
# The built in ruby Pathname#cleanpath method does not clean up forward slashes and
|
|
129
|
+
# backslashes. This is a wrapper around that which does. In general this is NOT
|
|
130
|
+
# recommended for internal use within ruby/chef since ruby does not care about forward slashes
|
|
131
|
+
# vs. backslashes, even on Windows. Where this generally matters is when being rendered
|
|
132
|
+
# to the user, or being rendered into things like the windows PATH or to commands that
|
|
133
|
+
# are being executed. In some cases it may be easier on windows to render paths to
|
|
134
|
+
# unix-style for being eventually eval'd by ruby in the future (templates being rendered
|
|
135
|
+
# with code to be consumed by ruby) where forcing unix-style forward slashes avoids the
|
|
136
|
+
# issue of needing to escape the backslashes in rendered strings. This has a boolean
|
|
137
|
+
# operator to force windows-style or non-windows style operation, where the default is
|
|
138
|
+
# determined by the underlying node['platform'] value.
|
|
139
|
+
#
|
|
140
|
+
# In general if you don't know if you need this routine, do not use it, best practice
|
|
141
|
+
# within chef/ruby itself is not to care. Only use it to force windows or unix style
|
|
142
|
+
# when it really matters.
|
|
137
143
|
#
|
|
138
|
-
#
|
|
139
|
-
#
|
|
140
|
-
|
|
144
|
+
# @param path [String] the path to clean
|
|
145
|
+
# @param windows [Boolean] optional flag to force to windows or unix-style
|
|
146
|
+
# @return [String] cleaned path
|
|
147
|
+
#
|
|
148
|
+
def self.cleanpath(path, windows: ChefUtils.windows?)
|
|
141
149
|
path = Pathname.new(path).cleanpath.to_s
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
path
|
|
150
|
+
if windows
|
|
151
|
+
# ensure all forward slashes are backslashes
|
|
152
|
+
path.gsub(File::SEPARATOR, path_separator(windows: windows))
|
|
153
|
+
else
|
|
154
|
+
# ensure all backslashes are forward slashes
|
|
155
|
+
path.gsub(BACKSLASH, File::SEPARATOR)
|
|
145
156
|
end
|
|
146
|
-
path
|
|
147
157
|
end
|
|
148
158
|
|
|
149
|
-
|
|
150
|
-
|
|
159
|
+
# This is not just escaping for something like use in Regexps, or in globs. For the former
|
|
160
|
+
# just use Regexp.escape. For the latter, use escape_glob_dir below.
|
|
161
|
+
#
|
|
162
|
+
# This is escaping where the path to be rendered is being put into a ruby file which will
|
|
163
|
+
# later be read back by ruby (or something similar) so we need quadruple backslashes.
|
|
164
|
+
#
|
|
165
|
+
# In order to print:
|
|
166
|
+
#
|
|
167
|
+
# file_cache_path "C:\\chef"
|
|
168
|
+
#
|
|
169
|
+
# We need to convert "C:\chef" to "C:\\\\chef" to interpolate into a string which is rendered
|
|
170
|
+
# into the output file with that line in it.
|
|
171
|
+
#
|
|
172
|
+
# @param path [String] the path to escape
|
|
173
|
+
# @return [String] the escaped path
|
|
174
|
+
#
|
|
175
|
+
def self.escapepath(path)
|
|
176
|
+
path.gsub(BACKSLASH, BACKSLASH * 4)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def self.paths_eql?(path1, path2, windows: ChefUtils.windows?)
|
|
180
|
+
canonical_path(path1, windows: windows) == canonical_path(path2, windows: windows)
|
|
151
181
|
end
|
|
152
182
|
|
|
153
183
|
# @deprecated this method is deprecated. Please use escape_glob_dirs
|
|
154
184
|
# Paths which may contain glob-reserved characters need
|
|
155
185
|
# to be escaped before globbing can be done.
|
|
156
186
|
# http://stackoverflow.com/questions/14127343
|
|
157
|
-
def self.escape_glob(*parts)
|
|
158
|
-
path = cleanpath(join(*parts))
|
|
187
|
+
def self.escape_glob(*parts, windows: ChefUtils.windows?)
|
|
188
|
+
path = cleanpath(join(*parts, windows: windows), windows: windows)
|
|
159
189
|
path.gsub(/[\\\{\}\[\]\*\?]/) { |x| "\\" + x }
|
|
160
190
|
end
|
|
161
191
|
|
|
@@ -166,8 +196,8 @@ module ChefConfig
|
|
|
166
196
|
path.gsub(/[\\\{\}\[\]\*\?]/) { |x| "\\" + x }
|
|
167
197
|
end
|
|
168
198
|
|
|
169
|
-
def self.relative_path_from(from, to)
|
|
170
|
-
Pathname.new(cleanpath(to)).relative_path_from(Pathname.new(cleanpath(from)))
|
|
199
|
+
def self.relative_path_from(from, to, windows: ChefUtils.windows?)
|
|
200
|
+
Pathname.new(cleanpath(to, windows: windows)).relative_path_from(Pathname.new(cleanpath(from, windows: windows)))
|
|
171
201
|
end
|
|
172
202
|
|
|
173
203
|
# Set the project-specific home directory environment variable.
|
|
@@ -213,11 +243,11 @@ module ChefConfig
|
|
|
213
243
|
#
|
|
214
244
|
# The return is a list of all the returned values from each block invocation or a list of paths
|
|
215
245
|
# if no block is provided.
|
|
216
|
-
def self.all_homes(*args)
|
|
246
|
+
def self.all_homes(*args, windows: ChefUtils.windows?)
|
|
217
247
|
paths = []
|
|
218
248
|
paths << ENV[@@per_tool_home_environment] if defined?(@@per_tool_home_environment) && @@per_tool_home_environment && ENV[@@per_tool_home_environment]
|
|
219
249
|
paths << ENV["CHEF_HOME"] if ENV["CHEF_HOME"]
|
|
220
|
-
if
|
|
250
|
+
if windows
|
|
221
251
|
# By default, Ruby uses the the following environment variables to determine Dir.home:
|
|
222
252
|
# HOME
|
|
223
253
|
# HOMEDRIVE HOMEPATH
|
|
@@ -246,7 +276,7 @@ module ChefConfig
|
|
|
246
276
|
# Note: Maybe this is a bad idea on some unixy systems where \ might be a valid character depending on
|
|
247
277
|
# the particular brand of kool-aid you consume. This code assumes that \ and / are both
|
|
248
278
|
# path separators on any system being used.
|
|
249
|
-
paths = paths.map { |home_path| home_path.gsub(path_separator, ::File::SEPARATOR) if home_path }
|
|
279
|
+
paths = paths.map { |home_path| home_path.gsub(path_separator(windows: windows), ::File::SEPARATOR) if home_path }
|
|
250
280
|
|
|
251
281
|
# Filter out duplicate paths and paths that don't exist.
|
|
252
282
|
valid_paths = paths.select { |home_path| home_path && Dir.exist?(home_path.force_encoding("utf-8")) }
|
data/lib/chef-config/version.rb
CHANGED
|
@@ -59,7 +59,7 @@ module ChefConfig
|
|
|
59
59
|
@chef_config_dir = false
|
|
60
60
|
full_path = working_directory.split(File::SEPARATOR)
|
|
61
61
|
(full_path.length - 1).downto(0) do |i|
|
|
62
|
-
candidate_directory = File.join(full_path[0..i] + [
|
|
62
|
+
candidate_directory = File.join(full_path[0..i] + [ChefUtils::Dist::Infra::USER_CONF_DIR])
|
|
63
63
|
if File.exist?(candidate_directory) && File.directory?(candidate_directory)
|
|
64
64
|
@chef_config_dir = candidate_directory
|
|
65
65
|
break
|
|
@@ -129,7 +129,7 @@ module ChefConfig
|
|
|
129
129
|
candidate_configs << File.join(chef_config_dir, "knife.rb")
|
|
130
130
|
end
|
|
131
131
|
# Look for $HOME/.chef/knife.rb
|
|
132
|
-
PathHelper.home(
|
|
132
|
+
PathHelper.home(ChefUtils::Dist::Infra::USER_CONF_DIR) do |dot_chef_dir|
|
|
133
133
|
candidate_configs << File.join(dot_chef_dir, "config.rb")
|
|
134
134
|
candidate_configs << File.join(dot_chef_dir, "knife.rb")
|
|
135
135
|
end
|
|
@@ -140,13 +140,11 @@ module ChefConfig
|
|
|
140
140
|
end
|
|
141
141
|
|
|
142
142
|
def working_directory
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
a
|
|
143
|
+
if ChefUtils.windows?
|
|
144
|
+
env["CD"]
|
|
145
|
+
else
|
|
146
|
+
env["PWD"]
|
|
147
|
+
end || Dir.pwd
|
|
150
148
|
end
|
|
151
149
|
|
|
152
150
|
def apply_credentials(creds, profile)
|
|
@@ -168,7 +166,7 @@ module ChefConfig
|
|
|
168
166
|
when "client_key"
|
|
169
167
|
extract_key(value, :client_key, :client_key_contents)
|
|
170
168
|
when "knife"
|
|
171
|
-
Config.knife.merge!(
|
|
169
|
+
Config.knife.merge!(value.transform_keys(&:to_sym))
|
|
172
170
|
else
|
|
173
171
|
Config[key.to_sym] = value
|
|
174
172
|
end
|
|
@@ -186,7 +184,7 @@ module ChefConfig
|
|
|
186
184
|
end
|
|
187
185
|
|
|
188
186
|
def home_chef_dir
|
|
189
|
-
@home_chef_dir ||= PathHelper.home(
|
|
187
|
+
@home_chef_dir ||= PathHelper.home(ChefUtils::Dist::Infra::USER_CONF_DIR)
|
|
190
188
|
end
|
|
191
189
|
|
|
192
190
|
def apply_config(config_content, config_file_path)
|
data/spec/unit/config_spec.rb
CHANGED
|
@@ -170,7 +170,7 @@ RSpec.describe ChefConfig::Config do
|
|
|
170
170
|
apply_config
|
|
171
171
|
expect(described_class[:data_bag_path]).to eq("#{current_directory}/data_bags")
|
|
172
172
|
expect(described_class[:cookbook_path]).to eq("#{current_directory}/cookbooks")
|
|
173
|
-
expect(described_class[:chef_repo_path]).to eq(
|
|
173
|
+
expect(described_class[:chef_repo_path]).to eq(current_directory)
|
|
174
174
|
end
|
|
175
175
|
end
|
|
176
176
|
|
|
@@ -222,13 +222,70 @@ RSpec.describe ChefConfig::Config do
|
|
|
222
222
|
ChefConfig::Config.add_formatter(:doc, "/var/log/formatter.log")
|
|
223
223
|
expect(ChefConfig::Config.formatters).to eq([[:doc, "/var/log/formatter.log"]])
|
|
224
224
|
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
describe "#var_chef_path" do
|
|
228
|
+
let (:dirname) { ChefUtils::Dist::Infra::DIR_SUFFIX }
|
|
229
|
+
|
|
230
|
+
context "on unix", :unix_only do
|
|
231
|
+
it "var_chef_dir is /var/chef" do
|
|
232
|
+
expect(ChefConfig::Config.var_chef_dir).to eql("/var/#{dirname}")
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
it "var_root_dir is /var" do
|
|
236
|
+
expect(ChefConfig::Config.var_root_dir).to eql("/var")
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
it "etc_chef_dir is /etc/chef" do
|
|
240
|
+
expect(ChefConfig::Config.etc_chef_dir).to eql("/etc/#{dirname}")
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
context "on windows", :windows_only do
|
|
245
|
+
it "var_chef_dir is C:\\chef" do
|
|
246
|
+
expect(ChefConfig::Config.var_chef_dir).to eql("C:\\#{dirname}")
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
it "var_root_dir is C:\\" do
|
|
250
|
+
expect(ChefConfig::Config.var_root_dir).to eql("C:\\")
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
it "etc_chef_dir is C:\\chef" do
|
|
254
|
+
expect(ChefConfig::Config.etc_chef_dir).to eql("C:\\#{dirname}")
|
|
255
|
+
end
|
|
256
|
+
end
|
|
225
257
|
|
|
258
|
+
context "when forced to unix" do
|
|
259
|
+
it "var_chef_dir is /var/chef" do
|
|
260
|
+
expect(ChefConfig::Config.var_chef_dir(windows: false)).to eql("/var/#{dirname}")
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
it "var_root_dir is /var" do
|
|
264
|
+
expect(ChefConfig::Config.var_root_dir(windows: false)).to eql("/var")
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
it "etc_chef_dir is /etc/chef" do
|
|
268
|
+
expect(ChefConfig::Config.etc_chef_dir(windows: false)).to eql("/etc/#{dirname}")
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
context "when forced to windows" do
|
|
273
|
+
it "var_chef_dir is C:\\chef" do
|
|
274
|
+
expect(ChefConfig::Config.var_chef_dir(windows: true)).to eql("C:\\#{dirname}")
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
it "var_root_dir is C:\\" do
|
|
278
|
+
expect(ChefConfig::Config.var_root_dir(windows: true)).to eql("C:\\")
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
it "etc_chef_dir is C:\\chef" do
|
|
282
|
+
expect(ChefConfig::Config.etc_chef_dir(windows: true)).to eql("C:\\#{dirname}")
|
|
283
|
+
end
|
|
284
|
+
end
|
|
226
285
|
end
|
|
227
286
|
|
|
228
287
|
[ false, true ].each do |is_windows|
|
|
229
|
-
|
|
230
288
|
context "On #{is_windows ? "Windows" : "Unix"}" do
|
|
231
|
-
|
|
232
289
|
before :each do
|
|
233
290
|
allow(ChefUtils).to receive(:windows?).and_return(is_windows)
|
|
234
291
|
end
|
|
@@ -430,8 +487,8 @@ RSpec.describe ChefConfig::Config do
|
|
|
430
487
|
|
|
431
488
|
describe "ChefConfig::Config[:cache_path]" do
|
|
432
489
|
let(:target_mode_host) { "fluffy.kittens.org" }
|
|
433
|
-
let(:target_mode_primary_cache_path) { "#{primary_cache_path}/#{target_mode_host}" }
|
|
434
|
-
let(:target_mode_secondary_cache_path) { "#{secondary_cache_path}/#{target_mode_host}" }
|
|
490
|
+
let(:target_mode_primary_cache_path) { ChefUtils.windows? ? "#{primary_cache_path}\\#{target_mode_host}" : "#{primary_cache_path}/#{target_mode_host}" }
|
|
491
|
+
let(:target_mode_secondary_cache_path) { ChefUtils.windows? ? "#{secondary_cache_path}\\#{target_mode_host}" : "#{secondary_cache_path}/#{target_mode_host}" }
|
|
435
492
|
|
|
436
493
|
before do
|
|
437
494
|
if is_windows
|
|
@@ -874,7 +931,7 @@ RSpec.describe ChefConfig::Config do
|
|
|
874
931
|
|
|
875
932
|
shared_examples_for "a suitable locale" do
|
|
876
933
|
it "returns an English UTF-8 locale" do
|
|
877
|
-
expect(ChefConfig.logger).to_not receive(:warn).with(/Please install an English UTF-8 locale for Chef to use/)
|
|
934
|
+
expect(ChefConfig.logger).to_not receive(:warn).with(/Please install an English UTF-8 locale for Chef Infra Client to use/)
|
|
878
935
|
expect(ChefConfig.logger).to_not receive(:trace).with(/Defaulting to locale en_US.UTF-8 on Windows/)
|
|
879
936
|
expect(ChefConfig.logger).to_not receive(:trace).with(/No usable locale -a command found/)
|
|
880
937
|
expect(ChefConfig::Config.guess_internal_locale).to eq expected_locale
|
|
@@ -927,7 +984,7 @@ RSpec.describe ChefConfig::Config do
|
|
|
927
984
|
let(:locale_array) { ["af_ZA", "af_ZA.ISO8859-1", "af_ZA.ISO8859-15", "af_ZA.UTF-8"] }
|
|
928
985
|
|
|
929
986
|
it "should fall back to C locale" do
|
|
930
|
-
expect(ChefConfig.logger).to receive(:warn).with("Please install an English UTF-8 locale for Chef to use, falling back to C locale and disabling UTF-8 support.")
|
|
987
|
+
expect(ChefConfig.logger).to receive(:warn).with("Please install an English UTF-8 locale for Chef Infra Client to use, falling back to C locale and disabling UTF-8 support.")
|
|
931
988
|
expect(ChefConfig::Config.guess_internal_locale).to eq "C"
|
|
932
989
|
end
|
|
933
990
|
end
|
data/spec/unit/fips_spec.rb
CHANGED
|
@@ -23,9 +23,8 @@ RSpec.describe ChefConfig::PathHelper do
|
|
|
23
23
|
|
|
24
24
|
let(:path_helper) { described_class }
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
context "common functionality" do
|
|
27
|
+
context "join" do
|
|
29
28
|
it "joins starting with '' resolve to absolute paths" do
|
|
30
29
|
expect(path_helper.join("", "a", "b")).to eq("#{path_helper.path_separator}a#{path_helper.path_separator}b")
|
|
31
30
|
end
|
|
@@ -33,10 +32,9 @@ RSpec.describe ChefConfig::PathHelper do
|
|
|
33
32
|
it "joins ending with '' add a / to the end" do
|
|
34
33
|
expect(path_helper.join("a", "b", "")).to eq("a#{path_helper.path_separator}b#{path_helper.path_separator}")
|
|
35
34
|
end
|
|
36
|
-
|
|
37
35
|
end
|
|
38
36
|
|
|
39
|
-
|
|
37
|
+
context "dirname" do
|
|
40
38
|
it "dirname('abc') is '.'" do
|
|
41
39
|
expect(path_helper.dirname("abc")).to eq(".")
|
|
42
40
|
end
|
|
@@ -55,42 +53,109 @@ RSpec.describe ChefConfig::PathHelper do
|
|
|
55
53
|
end
|
|
56
54
|
end
|
|
57
55
|
|
|
56
|
+
context "forcing windows/non-windows" do
|
|
57
|
+
context "forcing windows" do
|
|
58
|
+
it "path_separator is \\" do
|
|
59
|
+
expect(path_helper.path_separator(windows: true)).to eq('\\')
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
context "platform-specific #join behavior" do
|
|
63
|
+
it "joins components on Windows when some end with unix separators" do
|
|
64
|
+
expected = "C:\\foo\\bar\\baz"
|
|
65
|
+
expect(path_helper.join('C:\\foo/', "bar", "baz", windows: true)).to eq(expected)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "joins components when some end with separators" do
|
|
69
|
+
expected = "C:\\foo\\bar\\baz"
|
|
70
|
+
expect(path_helper.join('C:\\foo\\', "bar", "baz", windows: true)).to eq(expected)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "joins components when some end and start with separators" do
|
|
74
|
+
expected = "C:\\foo\\bar\\baz"
|
|
75
|
+
expect(path_helper.join('C:\\foo\\', "bar/", "/baz", windows: true)).to eq(expected)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "joins components that don't end in separators" do
|
|
79
|
+
expected = "C:\\foo\\bar\\baz"
|
|
80
|
+
expect(path_helper.join('C:\\foo', "bar", "baz", windows: true)).to eq(expected)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "cleanpath changes slashes into backslashes and leaves backslashes alone" do
|
|
85
|
+
expect(path_helper.cleanpath('/a/b\\c/d/', windows: true)).to eq('\\a\\b\\c\\d')
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "cleanpath does not remove leading double backslash" do
|
|
89
|
+
expect(path_helper.cleanpath('\\\\a/b\\c/d/', windows: true)).to eq('\\\\a\\b\\c\\d')
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
context "forcing unix" do
|
|
94
|
+
it "path_separator is /" do
|
|
95
|
+
expect(path_helper.path_separator(windows: false)).to eq("/")
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "cleanpath removes extra slashes alone" do
|
|
99
|
+
expect(path_helper.cleanpath("/a///b/c/d/", windows: false)).to eq("/a/b/c/d")
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
context "platform-specific #join behavior" do
|
|
103
|
+
it "joins components when some end with separators" do
|
|
104
|
+
expected = "/foo/bar/baz"
|
|
105
|
+
expect(path_helper.join("/foo/", "bar", "baz", windows: false)).to eq(expected)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "joins components when some end and start with separators" do
|
|
109
|
+
expected = "/foo/bar/baz"
|
|
110
|
+
expect(path_helper.join("/foo/", "bar/", "/baz", windows: false)).to eq(expected)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "joins components that don't end in separators" do
|
|
114
|
+
expected = "/foo/bar/baz"
|
|
115
|
+
expect(path_helper.join("/foo", "bar", "baz", windows: false)).to eq(expected)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "cleanpath changes backslashes into slashes and leaves slashes alone" do
|
|
120
|
+
expect(path_helper.cleanpath('/a/b\\c/d/', windows: false)).to eq("/a/b/c/d")
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "cleanpath does not remove leading double backslash" do
|
|
124
|
+
expect(path_helper.cleanpath('\\\\a/b\\c/d/', windows: false)).to eq("//a/b/c/d")
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
58
129
|
context "on windows", :windows_only do
|
|
59
130
|
|
|
60
131
|
before(:each) do
|
|
61
132
|
allow(ChefUtils).to receive(:windows?).and_return(true)
|
|
62
133
|
end
|
|
63
134
|
|
|
64
|
-
include_examples("common_functionality")
|
|
65
|
-
|
|
66
135
|
it "path_separator is \\" do
|
|
67
136
|
expect(path_helper.path_separator).to eq('\\')
|
|
68
137
|
end
|
|
69
138
|
|
|
70
|
-
|
|
71
|
-
|
|
139
|
+
context "platform-specific #join behavior" do
|
|
72
140
|
it "joins components on Windows when some end with unix separators" do
|
|
73
|
-
|
|
141
|
+
expected = "C:\\foo\\bar\\baz"
|
|
142
|
+
expect(path_helper.join('C:\\foo/', "bar", "baz")).to eq(expected)
|
|
74
143
|
end
|
|
75
144
|
|
|
76
145
|
it "joins components when some end with separators" do
|
|
77
|
-
expected =
|
|
78
|
-
expected = "C:#{expected}"
|
|
146
|
+
expected = "C:\\foo\\bar\\baz"
|
|
79
147
|
expect(path_helper.join('C:\\foo\\', "bar", "baz")).to eq(expected)
|
|
80
148
|
end
|
|
81
149
|
|
|
82
150
|
it "joins components when some end and start with separators" do
|
|
83
|
-
expected =
|
|
84
|
-
expected = "C:#{expected}"
|
|
151
|
+
expected = "C:\\foo\\bar\\baz"
|
|
85
152
|
expect(path_helper.join('C:\\foo\\', "bar/", "/baz")).to eq(expected)
|
|
86
153
|
end
|
|
87
154
|
|
|
88
155
|
it "joins components that don't end in separators" do
|
|
89
|
-
expected =
|
|
90
|
-
expected = "C:#{expected}"
|
|
156
|
+
expected = "C:\\foo\\bar\\baz"
|
|
91
157
|
expect(path_helper.join('C:\\foo', "bar", "baz")).to eq(expected)
|
|
92
158
|
end
|
|
93
|
-
|
|
94
159
|
end
|
|
95
160
|
|
|
96
161
|
it "cleanpath changes slashes into backslashes and leaves backslashes alone" do
|
|
@@ -100,17 +165,13 @@ RSpec.describe ChefConfig::PathHelper do
|
|
|
100
165
|
it "cleanpath does not remove leading double backslash" do
|
|
101
166
|
expect(path_helper.cleanpath('\\\\a/b\\c/d/')).to eq('\\\\a\\b\\c\\d')
|
|
102
167
|
end
|
|
103
|
-
|
|
104
168
|
end
|
|
105
169
|
|
|
106
170
|
context "on unix", :unix_only do
|
|
107
|
-
|
|
108
171
|
before(:each) do
|
|
109
172
|
allow(ChefUtils).to receive(:windows?).and_return(false)
|
|
110
173
|
end
|
|
111
174
|
|
|
112
|
-
include_examples("common_functionality")
|
|
113
|
-
|
|
114
175
|
it "path_separator is /" do
|
|
115
176
|
expect(path_helper.path_separator).to eq("/")
|
|
116
177
|
end
|
|
@@ -119,8 +180,7 @@ RSpec.describe ChefConfig::PathHelper do
|
|
|
119
180
|
expect(path_helper.cleanpath("/a///b/c/d/")).to eq("/a/b/c/d")
|
|
120
181
|
end
|
|
121
182
|
|
|
122
|
-
|
|
123
|
-
|
|
183
|
+
context "platform-specific #join behavior" do
|
|
124
184
|
it "joins components when some end with separators" do
|
|
125
185
|
expected = path_helper.cleanpath("/foo/bar/baz")
|
|
126
186
|
expect(path_helper.join("/foo/", "bar", "baz")).to eq(expected)
|
|
@@ -135,12 +195,19 @@ RSpec.describe ChefConfig::PathHelper do
|
|
|
135
195
|
expected = path_helper.cleanpath("/foo/bar/baz")
|
|
136
196
|
expect(path_helper.join("/foo", "bar", "baz")).to eq(expected)
|
|
137
197
|
end
|
|
198
|
+
end
|
|
138
199
|
|
|
200
|
+
it "cleanpath changes backslashes into slashes and leaves slashes alone" do
|
|
201
|
+
expect(path_helper.cleanpath('/a/b\\c/d/', windows: false)).to eq("/a/b/c/d")
|
|
139
202
|
end
|
|
140
203
|
|
|
204
|
+
# NOTE: this seems a bit weird to me, but this is just the way Pathname#cleanpath works
|
|
205
|
+
it "cleanpath does not remove leading double backslash" do
|
|
206
|
+
expect(path_helper.cleanpath('\\\\a/b\\c/d/')).to eq("//a/b/c/d")
|
|
207
|
+
end
|
|
141
208
|
end
|
|
142
209
|
|
|
143
|
-
|
|
210
|
+
context "validate_path" do
|
|
144
211
|
context "on windows" do
|
|
145
212
|
before(:each) do
|
|
146
213
|
# pass by default
|
|
@@ -171,7 +238,7 @@ RSpec.describe ChefConfig::PathHelper do
|
|
|
171
238
|
end
|
|
172
239
|
end
|
|
173
240
|
|
|
174
|
-
|
|
241
|
+
context "windows_max_length_exceeded?" do
|
|
175
242
|
it "returns true if the path is too long (259 + NUL) for the API" do
|
|
176
243
|
expect(path_helper.windows_max_length_exceeded?("C:\\" + "a" * 250 + "\\" + "b" * 6)).to be_truthy
|
|
177
244
|
end
|
|
@@ -185,7 +252,7 @@ RSpec.describe ChefConfig::PathHelper do
|
|
|
185
252
|
end
|
|
186
253
|
end
|
|
187
254
|
|
|
188
|
-
|
|
255
|
+
context "printable?" do
|
|
189
256
|
it "returns true if the string contains no non-printable characters" do
|
|
190
257
|
expect(path_helper.printable?("C:\\Program Files (x86)\\Microsoft Office\\Files.lst")).to be_truthy
|
|
191
258
|
end
|
|
@@ -208,7 +275,7 @@ RSpec.describe ChefConfig::PathHelper do
|
|
|
208
275
|
end
|
|
209
276
|
end
|
|
210
277
|
|
|
211
|
-
|
|
278
|
+
context "canonical_path" do
|
|
212
279
|
context "on windows", :windows_only do
|
|
213
280
|
it "returns an absolute path with backslashes instead of slashes" do
|
|
214
281
|
expect(path_helper.canonical_path("\\\\?\\C:/windows/win.ini")).to eq("\\\\?\\c:\\windows\\win.ini")
|
|
@@ -230,25 +297,25 @@ RSpec.describe ChefConfig::PathHelper do
|
|
|
230
297
|
end
|
|
231
298
|
end
|
|
232
299
|
|
|
233
|
-
|
|
300
|
+
context "paths_eql?" do
|
|
234
301
|
it "returns true if the paths are the same" do
|
|
235
|
-
allow(path_helper).to receive(:canonical_path).with("bandit").and_return("c:/bandit/bandit")
|
|
236
|
-
allow(path_helper).to receive(:canonical_path).with("../bandit/bandit").and_return("c:/bandit/bandit")
|
|
302
|
+
allow(path_helper).to receive(:canonical_path).with("bandit", windows: ChefUtils.windows?).and_return("c:/bandit/bandit")
|
|
303
|
+
allow(path_helper).to receive(:canonical_path).with("../bandit/bandit", windows: ChefUtils.windows?).and_return("c:/bandit/bandit")
|
|
237
304
|
expect(path_helper.paths_eql?("bandit", "../bandit/bandit")).to be_truthy
|
|
238
305
|
end
|
|
239
306
|
|
|
240
307
|
it "returns false if the paths are different" do
|
|
241
|
-
allow(path_helper).to receive(:canonical_path).with("bandit").and_return("c:/Bo/Bandit")
|
|
242
|
-
allow(path_helper).to receive(:canonical_path).with("../bandit/bandit").and_return("c:/bandit/bandit")
|
|
308
|
+
allow(path_helper).to receive(:canonical_path).with("bandit", windows: ChefUtils.windows?).and_return("c:/Bo/Bandit")
|
|
309
|
+
allow(path_helper).to receive(:canonical_path).with("../bandit/bandit", windows: ChefUtils.windows?).and_return("c:/bandit/bandit")
|
|
243
310
|
expect(path_helper.paths_eql?("bandit", "../bandit/bandit")).to be_falsey
|
|
244
311
|
end
|
|
245
312
|
end
|
|
246
313
|
|
|
247
|
-
|
|
314
|
+
context "escape_glob" do
|
|
248
315
|
it "escapes characters reserved by glob" do
|
|
249
316
|
path = "C:\\this\\*path\\[needs]\\escaping?"
|
|
250
317
|
escaped_path = "C:\\\\this\\\\\\*path\\\\\\[needs\\]\\\\escaping\\?"
|
|
251
|
-
expect(path_helper.escape_glob(path)).to eq(escaped_path)
|
|
318
|
+
expect(path_helper.escape_glob(path, windows: true)).to eq(escaped_path)
|
|
252
319
|
end
|
|
253
320
|
|
|
254
321
|
context "when given more than one argument" do
|
|
@@ -259,14 +326,12 @@ RSpec.describe ChefConfig::PathHelper do
|
|
|
259
326
|
else
|
|
260
327
|
"this/\\*path/\\[needs\\]/escaping\\?"
|
|
261
328
|
end
|
|
262
|
-
expect(path_helper).to receive(:join).with(*args).and_call_original
|
|
263
|
-
expect(path_helper).to receive(:cleanpath).and_call_original
|
|
264
329
|
expect(path_helper.escape_glob(*args)).to eq(escaped_path)
|
|
265
330
|
end
|
|
266
331
|
end
|
|
267
332
|
end
|
|
268
333
|
|
|
269
|
-
|
|
334
|
+
context "escape_glob_dir" do
|
|
270
335
|
it "escapes characters reserved by glob without using backslashes for path separators" do
|
|
271
336
|
path = "C:/this/*path/[needs]/escaping?"
|
|
272
337
|
escaped_path = "C:/this/\\*path/\\[needs\\]/escaping\\?"
|
|
@@ -283,7 +348,7 @@ RSpec.describe ChefConfig::PathHelper do
|
|
|
283
348
|
end
|
|
284
349
|
end
|
|
285
350
|
|
|
286
|
-
|
|
351
|
+
context "all_homes" do
|
|
287
352
|
before do
|
|
288
353
|
stub_const("ENV", env)
|
|
289
354
|
allow(ChefUtils).to receive(:windows?).and_return(is_windows)
|
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: 16.
|
|
4
|
+
version: 16.5.77
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Adam Jacob
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-
|
|
11
|
+
date: 2020-09-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: chef-utils
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - '='
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 16.
|
|
19
|
+
version: 16.5.77
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - '='
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 16.
|
|
26
|
+
version: 16.5.77
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: mixlib-shellout
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -174,13 +174,13 @@ files:
|
|
|
174
174
|
- chef-config.gemspec
|
|
175
175
|
- lib/chef-config.rb
|
|
176
176
|
- lib/chef-config/config.rb
|
|
177
|
-
- lib/chef-config/dist.rb
|
|
178
177
|
- lib/chef-config/exceptions.rb
|
|
179
178
|
- lib/chef-config/fips.rb
|
|
180
179
|
- lib/chef-config/logger.rb
|
|
181
180
|
- lib/chef-config/mixin/credentials.rb
|
|
182
181
|
- lib/chef-config/mixin/dot_d.rb
|
|
183
182
|
- lib/chef-config/mixin/fuzzy_hostname_matcher.rb
|
|
183
|
+
- lib/chef-config/mixin/train_transport.rb
|
|
184
184
|
- lib/chef-config/path_helper.rb
|
|
185
185
|
- lib/chef-config/version.rb
|
|
186
186
|
- lib/chef-config/windows.rb
|
data/lib/chef-config/dist.rb
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
module ChefConfig
|
|
2
|
-
class Dist
|
|
3
|
-
# The chef executable name.
|
|
4
|
-
EXEC = "chef".freeze
|
|
5
|
-
|
|
6
|
-
# The client's alias (chef-client)
|
|
7
|
-
CLIENT = "chef-client".freeze
|
|
8
|
-
|
|
9
|
-
# A short name for the product
|
|
10
|
-
SHORT = "chef".freeze
|
|
11
|
-
|
|
12
|
-
# The suffix for Chef's /etc/chef, /var/chef and C:\\Chef directories
|
|
13
|
-
# "cinc" => /etc/cinc, /var/cinc, C:\\cinc
|
|
14
|
-
DIR_SUFFIX = "chef".freeze
|
|
15
|
-
|
|
16
|
-
# The user's configuration directory
|
|
17
|
-
USER_CONF_DIR = ".chef".freeze
|
|
18
|
-
|
|
19
|
-
# The legacy conf folder: C:/opscode/chef. Specifically the "opscode" part
|
|
20
|
-
# DIR_SUFFIX is appended to it in code where relevant
|
|
21
|
-
LEGACY_CONF_DIR = "opscode".freeze
|
|
22
|
-
|
|
23
|
-
# Enable forcing Chef EULA
|
|
24
|
-
ENFORCE_LICENSE = true
|
|
25
|
-
end
|
|
26
|
-
end
|