chef 18.4.2 → 18.5.0

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.
Files changed (223) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -1
  3. data/chef.gemspec +7 -7
  4. data/lib/chef/application/client.rb +12 -0
  5. data/lib/chef/client.rb +10 -16
  6. data/lib/chef/compliance/runner.rb +10 -0
  7. data/lib/chef/cookbook/chefignore.rb +4 -1
  8. data/lib/chef/cookbook/cookbook_version_loader.rb +1 -1
  9. data/lib/chef/cookbook/synchronizer.rb +7 -1
  10. data/lib/chef/cookbook_manifest.rb +2 -2
  11. data/lib/chef/file_access_control/unix.rb +9 -9
  12. data/lib/chef/file_cache.rb +17 -2
  13. data/lib/chef/file_content_management/deploy/target_io.rb +29 -0
  14. data/lib/chef/file_content_management/deploy.rb +4 -1
  15. data/lib/chef/formatters/doc.rb +1 -1
  16. data/lib/chef/mixin/file_class.rb +3 -1
  17. data/lib/chef/mixin/get_source_from_package.rb +1 -1
  18. data/lib/chef/mixin/openssl_helper.rb +1 -1
  19. data/lib/chef/node/attribute.rb +3 -11
  20. data/lib/chef/node/immutable_collections.rb +15 -8
  21. data/lib/chef/node/mixin/state_tracking.rb +6 -3
  22. data/lib/chef/node.rb +1 -1
  23. data/lib/chef/policy_builder/policyfile.rb +8 -0
  24. data/lib/chef/provider/.gitkeep +0 -0
  25. data/lib/chef/provider/cookbook_file.rb +1 -1
  26. data/lib/chef/provider/cron.rb +1 -1
  27. data/lib/chef/provider/directory.rb +15 -15
  28. data/lib/chef/provider/file.rb +42 -29
  29. data/lib/chef/provider/git.rb +8 -8
  30. data/lib/chef/provider/group/aix.rb +1 -1
  31. data/lib/chef/provider/group/dscl.rb +1 -1
  32. data/lib/chef/provider/group/gpasswd.rb +2 -2
  33. data/lib/chef/provider/group/groupadd.rb +1 -1
  34. data/lib/chef/provider/group/groupmod.rb +2 -2
  35. data/lib/chef/provider/group/pw.rb +2 -2
  36. data/lib/chef/provider/group/solaris.rb +2 -2
  37. data/lib/chef/provider/group/usermod.rb +2 -2
  38. data/lib/chef/provider/group.rb +1 -1
  39. data/lib/chef/provider/http_request.rb +2 -3
  40. data/lib/chef/provider/ifconfig/aix.rb +1 -1
  41. data/lib/chef/provider/ifconfig/debian.rb +3 -3
  42. data/lib/chef/provider/ifconfig/redhat.rb +1 -1
  43. data/lib/chef/provider/ifconfig.rb +1 -1
  44. data/lib/chef/provider/link.rb +10 -10
  45. data/lib/chef/provider/mount/aix.rb +4 -4
  46. data/lib/chef/provider/mount/linux.rb +4 -4
  47. data/lib/chef/provider/mount/mount.rb +11 -11
  48. data/lib/chef/provider/package/apt.rb +2 -11
  49. data/lib/chef/provider/package/bff.rb +3 -3
  50. data/lib/chef/provider/package/chocolatey.rb +54 -24
  51. data/lib/chef/provider/package/dpkg.rb +3 -3
  52. data/lib/chef/provider/package/freebsd/base.rb +1 -1
  53. data/lib/chef/provider/package/habitat.rb +5 -3
  54. data/lib/chef/provider/package/ips.rb +2 -2
  55. data/lib/chef/provider/package/openbsd.rb +3 -2
  56. data/lib/chef/provider/package/pacman.rb +4 -4
  57. data/lib/chef/provider/package/paludis.rb +2 -2
  58. data/lib/chef/provider/package/portage.rb +1 -1
  59. data/lib/chef/provider/package/powershell.rb +1 -0
  60. data/lib/chef/provider/package/rpm.rb +2 -2
  61. data/lib/chef/provider/package/smartos.rb +2 -2
  62. data/lib/chef/provider/package/snap.rb +2 -1
  63. data/lib/chef/provider/package/snap_tm.rb +79 -0
  64. data/lib/chef/provider/package/solaris.rb +4 -4
  65. data/lib/chef/provider/package/zypper.rb +4 -5
  66. data/lib/chef/provider/package.rb +1 -1
  67. data/lib/chef/provider/remote_directory.rb +5 -5
  68. data/lib/chef/provider/remote_file/http.rb +2 -3
  69. data/lib/chef/provider/remote_file.rb +1 -1
  70. data/lib/chef/provider/route.rb +9 -9
  71. data/lib/chef/provider/service/aix.rb +1 -1
  72. data/lib/chef/provider/service/aixinit.rb +4 -4
  73. data/lib/chef/provider/service/arch.rb +6 -6
  74. data/lib/chef/provider/service/debian.rb +5 -5
  75. data/lib/chef/provider/service/freebsd.rb +7 -7
  76. data/lib/chef/provider/service/gentoo.rb +5 -5
  77. data/lib/chef/provider/service/init.rb +2 -2
  78. data/lib/chef/provider/service/insserv.rb +2 -2
  79. data/lib/chef/provider/service/invokercd.rb +1 -1
  80. data/lib/chef/provider/service/openbsd.rb +7 -7
  81. data/lib/chef/provider/service/redhat.rb +3 -3
  82. data/lib/chef/provider/service/solaris.rb +2 -2
  83. data/lib/chef/provider/service/systemd.rb +2 -2
  84. data/lib/chef/provider/service/upstart.rb +2 -2
  85. data/lib/chef/provider/service/windows.rb +0 -1
  86. data/lib/chef/provider/subversion.rb +8 -8
  87. data/lib/chef/provider/systemd_unit.rb +3 -3
  88. data/lib/chef/provider/template.rb +1 -1
  89. data/lib/chef/provider/user/aix.rb +3 -3
  90. data/lib/chef/provider/user/linux.rb +7 -2
  91. data/lib/chef/provider/user/pw.rb +3 -3
  92. data/lib/chef/provider/user/solaris.rb +7 -7
  93. data/lib/chef/provider/user.rb +7 -8
  94. data/lib/chef/provider/yum_repository.rb +1 -3
  95. data/lib/chef/provider/zypper_repository.rb +1 -1
  96. data/lib/chef/providers.rb +1 -0
  97. data/lib/chef/resource/.gitkeep +0 -0
  98. data/lib/chef/resource/alternatives.rb +2 -2
  99. data/lib/chef/resource/apt_preference.rb +1 -1
  100. data/lib/chef/resource/apt_repository.rb +7 -9
  101. data/lib/chef/resource/apt_update.rb +3 -3
  102. data/lib/chef/resource/bff_package.rb +1 -1
  103. data/lib/chef/resource/chef_client_config.rb +3 -2
  104. data/lib/chef/resource/chef_client_systemd_timer.rb +5 -0
  105. data/lib/chef/resource/chef_gem.rb +1 -1
  106. data/lib/chef/resource/chef_sleep.rb +1 -1
  107. data/lib/chef/resource/cookbook_file.rb +1 -1
  108. data/lib/chef/resource/cron/cron.rb +1 -1
  109. data/lib/chef/resource/cron/cron_d.rb +1 -1
  110. data/lib/chef/resource/cron_access.rb +1 -1
  111. data/lib/chef/resource/directory.rb +1 -1
  112. data/lib/chef/resource/dpkg_package.rb +1 -1
  113. data/lib/chef/resource/execute.rb +8 -6
  114. data/lib/chef/resource/file/verification/json.rb +1 -1
  115. data/lib/chef/resource/file/verification/systemd_unit.rb +1 -1
  116. data/lib/chef/resource/file/verification/yaml.rb +1 -1
  117. data/lib/chef/resource/file.rb +1 -1
  118. data/lib/chef/resource/freebsd_package.rb +2 -2
  119. data/lib/chef/resource/group.rb +1 -1
  120. data/lib/chef/resource/habitat/habitat_package.rb +1 -1
  121. data/lib/chef/resource/habitat/habitat_sup.rb +9 -9
  122. data/lib/chef/resource/habitat/habitat_sup_systemd.rb +2 -2
  123. data/lib/chef/resource/habitat_install.rb +5 -4
  124. data/lib/chef/resource/hostname.rb +11 -10
  125. data/lib/chef/resource/http_request.rb +1 -1
  126. data/lib/chef/resource/ifconfig.rb +1 -1
  127. data/lib/chef/resource/inspec_input.rb +3 -1
  128. data/lib/chef/resource/inspec_waiver.rb +1 -1
  129. data/lib/chef/resource/inspec_waiver_file_entry.rb +1 -1
  130. data/lib/chef/resource/ips_package.rb +2 -2
  131. data/lib/chef/resource/kernel_module.rb +2 -2
  132. data/lib/chef/resource/link.rb +1 -1
  133. data/lib/chef/resource/locale.rb +2 -2
  134. data/lib/chef/resource/mount.rb +1 -1
  135. data/lib/chef/resource/notify_group.rb +1 -1
  136. data/lib/chef/resource/ohai.rb +1 -1
  137. data/lib/chef/resource/ohai_hint.rb +1 -1
  138. data/lib/chef/resource/openbsd_package.rb +2 -2
  139. data/lib/chef/resource/package.rb +1 -1
  140. data/lib/chef/resource/pacman_package.rb +1 -1
  141. data/lib/chef/resource/paludis_package.rb +1 -1
  142. data/lib/chef/resource/portage_package.rb +1 -1
  143. data/lib/chef/resource/powershell_package.rb +4 -0
  144. data/lib/chef/resource/reboot.rb +1 -1
  145. data/lib/chef/resource/remote_directory.rb +1 -1
  146. data/lib/chef/resource/remote_file.rb +1 -1
  147. data/lib/chef/resource/rhsm_errata.rb +1 -1
  148. data/lib/chef/resource/rhsm_errata_level.rb +1 -1
  149. data/lib/chef/resource/rhsm_register.rb +1 -1
  150. data/lib/chef/resource/rhsm_repo.rb +3 -4
  151. data/lib/chef/resource/rhsm_subscription.rb +8 -9
  152. data/lib/chef/resource/route.rb +1 -1
  153. data/lib/chef/resource/rpm_package.rb +1 -1
  154. data/lib/chef/resource/scm/git.rb +1 -1
  155. data/lib/chef/resource/scm/subversion.rb +1 -1
  156. data/lib/chef/resource/selinux/common_helpers.rb +1 -1
  157. data/lib/chef/resource/selinux_boolean.rb +1 -1
  158. data/lib/chef/resource/selinux_fcontext.rb +3 -3
  159. data/lib/chef/resource/selinux_install.rb +1 -1
  160. data/lib/chef/resource/selinux_login.rb +1 -1
  161. data/lib/chef/resource/selinux_module.rb +5 -5
  162. data/lib/chef/resource/selinux_permissive.rb +2 -2
  163. data/lib/chef/resource/selinux_port.rb +2 -2
  164. data/lib/chef/resource/selinux_state.rb +2 -2
  165. data/lib/chef/resource/selinux_user.rb +1 -1
  166. data/lib/chef/resource/smartos_package.rb +2 -2
  167. data/lib/chef/resource/snap_package.rb +24 -1
  168. data/lib/chef/resource/solaris_package.rb +1 -1
  169. data/lib/chef/resource/ssh_known_hosts_entry.rb +1 -1
  170. data/lib/chef/resource/sudo.rb +5 -5
  171. data/lib/chef/resource/support/client.erb +1 -1
  172. data/lib/chef/resource/swap_file.rb +6 -6
  173. data/lib/chef/resource/sysctl.rb +6 -5
  174. data/lib/chef/resource/systemd_unit.rb +1 -1
  175. data/lib/chef/resource/template.rb +1 -1
  176. data/lib/chef/resource/timezone.rb +5 -5
  177. data/lib/chef/resource/user/aix_user.rb +2 -2
  178. data/lib/chef/resource/user/linux_user.rb +2 -2
  179. data/lib/chef/resource/user/pw_user.rb +2 -2
  180. data/lib/chef/resource/user/solaris_user.rb +2 -2
  181. data/lib/chef/resource/user_ulimit.rb +1 -1
  182. data/lib/chef/resource/yum_repository.rb +1 -1
  183. data/lib/chef/resource/zypper_package.rb +2 -2
  184. data/lib/chef/resource/zypper_repository.rb +2 -2
  185. data/lib/chef/run_lock.rb +3 -0
  186. data/lib/chef/scan_access_control.rb +6 -6
  187. data/lib/chef/target_io/dir.rb +12 -0
  188. data/lib/chef/target_io/etc.rb +16 -0
  189. data/lib/chef/target_io/file.rb +12 -0
  190. data/lib/chef/target_io/fileutils.rb +12 -0
  191. data/lib/chef/target_io/http.rb +22 -0
  192. data/lib/chef/target_io/io.rb +12 -0
  193. data/lib/chef/target_io/shadow.rb +44 -0
  194. data/lib/chef/target_io/train/dir.rb +69 -0
  195. data/lib/chef/target_io/train/etc.rb +112 -0
  196. data/lib/chef/target_io/train/file.rb +219 -0
  197. data/lib/chef/target_io/train/fileutils.rb +220 -0
  198. data/lib/chef/target_io/train/http.rb +117 -0
  199. data/lib/chef/target_io/train/io.rb +13 -0
  200. data/lib/chef/target_io/train/shadow.rb +52 -0
  201. data/lib/chef/target_io/train_compat.rb +7 -0
  202. data/lib/chef/target_io.rb +9 -0
  203. data/lib/chef/util/backup.rb +1 -1
  204. data/lib/chef/util/diff.rb +14 -1
  205. data/lib/chef/util/file_edit.rb +4 -4
  206. data/lib/chef/version.rb +1 -1
  207. data/lib/chef.rb +2 -0
  208. data/spec/functional/resource/remote_file_spec.rb +1 -1
  209. data/spec/integration/client/fips_spec.rb +11 -2
  210. data/spec/integration/client/open_ssl_spec.rb +20 -0
  211. data/spec/spec_helper.rb +3 -1
  212. data/spec/support/platform_helpers.rb +20 -7
  213. data/spec/unit/client_spec.rb +0 -16
  214. data/spec/unit/file_cache_spec.rb +64 -0
  215. data/spec/unit/mixin/openssl_helper_spec.rb +6 -1
  216. data/spec/unit/provider/apt_repository_spec.rb +1 -1
  217. data/spec/unit/provider/package/chocolatey_spec.rb +17 -12
  218. data/spec/unit/provider/package/windows_spec.rb +5 -5
  219. data/spec/unit/provider/package/zypper_spec.rb +0 -10
  220. data/spec/unit/provider/route_spec.rb +6 -4
  221. data/spec/unit/resource/rhsm_repo_spec.rb +1 -0
  222. data/spec/unit/resource/rhsm_subscription_spec.rb +2 -0
  223. metadata +31 -10
@@ -0,0 +1,69 @@
1
+ require_relative "file"
2
+ require_relative "fileutils"
3
+
4
+ module TargetIO
5
+ module TrainCompat
6
+ class Dir
7
+ class << self
8
+ # TODO: chdir, mktmpdir, pwd, home (Used in Resources)
9
+
10
+ def [](*patterns, base: ".", sort: true)
11
+ Dir.glob(patterns, 0, base, sort)
12
+ end
13
+
14
+ def delete(dir_name)
15
+ ::TargetIO::FileUtils.rm_rf(dir_name)
16
+ end
17
+
18
+ def directory?(dir_name)
19
+ ::TargetIO::File.directory? dir_name
20
+ end
21
+
22
+ def entries(dirname)
23
+ cmd = "ls -1a #{dirname}"
24
+ output = __run_command(cmd).stdout
25
+ output.split("\n")
26
+ end
27
+
28
+ def glob(pattern, flags = 0, base: ".", sort: true)
29
+ raise "Dir.glob flags not supported except FNM_DOTMATCH" unless [0, ::File::FNM_DOTMATCH].include? flags
30
+
31
+ pattern = Array(pattern)
32
+ matchdot = flags || ::File::FNM_DOTMATCH ? "dotglob" : ""
33
+
34
+ # TODO: Check for bash remotely
35
+ cmd += <<-BASH4
36
+ shopt -s globstar #{matchdot}
37
+ cd #{base}
38
+ for f in #{pattern.join(" ")}; do
39
+ printf '%s\n' "$f";
40
+ done
41
+ BASH4
42
+
43
+ output = __run_command(cmd).stdout
44
+ files = output.split("\n")
45
+ files.sort! if sort
46
+
47
+ files
48
+ end
49
+
50
+ def mkdir(dir_name, mode = nil)
51
+ ::TargetIO::FileUtils.mkdir(dir_name)
52
+ ::TargetIO::FileUtils.chmod(dir_name, mode) if mode
53
+ end
54
+
55
+ def unlink(dir_name)
56
+ ::TargetIO::FileUtils.rmdir(dir_name)
57
+ end
58
+
59
+ def __run_command(cmd)
60
+ __transport_connection.run_command(cmd)
61
+ end
62
+
63
+ def __transport_connection
64
+ Chef.run_context&.transport_connection
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,112 @@
1
+ require_relative "file"
2
+
3
+ module TargetIO
4
+ module TrainCompat
5
+ class Etc
6
+ @@cache = {}
7
+
8
+ class << self
9
+ def getpwnam(name)
10
+ __getpw { |entry| entry["user"] == name }
11
+ end
12
+
13
+ def getpwuid(uid)
14
+ __getpw { |entry| entry["uid"] == uid.to_i }
15
+ end
16
+
17
+ def getgrnam(name)
18
+ __getgr { |entry| entry["name"] == name }
19
+ end
20
+
21
+ def getgrgid(gid)
22
+ __getgr { |entry| entry["gid"] == gid.to_i }
23
+ end
24
+
25
+ def __getpw(&block)
26
+ content = ::TargetIO::File.read("/etc/passwd")
27
+ entries = __parse_passwd(content)
28
+ data = entries.detect(&block)
29
+ raise ArgumentError unless data
30
+
31
+ ::Etc::Passwd.new(
32
+ data["user"],
33
+ data["password"],
34
+ data["uid"].to_i,
35
+ data["gid"].to_i,
36
+ data["desc"],
37
+ data["home"],
38
+ data["shell"]
39
+ )
40
+ end
41
+
42
+ # Parse /etc/passwd files.
43
+ # Courtesy of InSpec
44
+ #
45
+ # @param [String] content the raw content of /etc/passwd
46
+ # @return [Array] Collection of passwd entries
47
+ def __parse_passwd(content)
48
+ content.to_s.split("\n").map do |line|
49
+ next if line[0] == "#"
50
+
51
+ __parse_passwd_line(line)
52
+ end.compact
53
+ end
54
+
55
+ # Parse a line of /etc/passwd
56
+ #
57
+ # @param [String] line a line of /etc/passwd
58
+ # @return [Hash] Map of entries in this line
59
+ def __parse_passwd_line(line)
60
+ x = line.split(":")
61
+ {
62
+ # rubocop:disable Layout/AlignHash
63
+ "user" => x.at(0),
64
+ "password" => x.at(1),
65
+ "uid" => x.at(2),
66
+ "gid" => x.at(3),
67
+ "desc" => x.at(4),
68
+ "home" => x.at(5),
69
+ "shell" => x.at(6),
70
+ }
71
+ end
72
+
73
+ def __getgr(&block)
74
+ content = ::TargetIO::File.read("/etc/group")
75
+ entries = __parse_group(content)
76
+ data = entries.detect(&block)
77
+ raise ArgumentError unless data
78
+
79
+ ::Etc::Group.new(
80
+ data["name"],
81
+ data["password"],
82
+ data["gid"].to_i,
83
+ String(data["mem"]).split(",")
84
+ )
85
+ end
86
+
87
+ def __parse_group(content)
88
+ content.to_s.split("\n").map do |line|
89
+ next if line[0] == "#"
90
+
91
+ __parse_group_line(line)
92
+ end.compact
93
+ end
94
+
95
+ def __parse_group_line(line)
96
+ x = line.split(":")
97
+ {
98
+ # rubocop:disable Layout/AlignHash
99
+ "name" => x.at(0),
100
+ "password" => x.at(1),
101
+ "gid" => x.at(2),
102
+ "mem" => x.at(3),
103
+ }
104
+ end
105
+
106
+ def __transport_connection
107
+ Chef.run_context&.transport_connection
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,219 @@
1
+ module TargetIO
2
+ module TrainCompat
3
+ class File
4
+ class << self
5
+ def foreach(name)
6
+ raise "TargetIO does not implement block-less File.foreach yet" unless block_given?
7
+
8
+ contents = readlines(name)
9
+ contents.each { |line| yield(line) }
10
+ end
11
+
12
+ def binread(name, length = nil, offset = 0)
13
+ content = read(file_name)
14
+ length = content.size - offset if length.nil?
15
+
16
+ content[offset, length]
17
+ end
18
+
19
+ def expand_path(file_name, dir_string = "")
20
+ require "pathname" unless defined?(Pathname)
21
+
22
+ # Will just collapse relative paths inside
23
+ pn = Pathname.new File.join(dir_string, file_name)
24
+ pn.cleanpath
25
+ end
26
+
27
+ def new(filename, mode = "r")
28
+ # Would need to hook into io.close (Closure?)
29
+ raise NotImplementedError, "TargetIO does not implement File.new yet"
30
+ end
31
+
32
+ def read(file_name)
33
+ readlines(file_name)&.join("\n") || ""
34
+ end
35
+
36
+ def open(file_name, mode = "r")
37
+ # Would need to hook into io.close (Closure?)
38
+ raise "TargetIO does not implement block-less File.open with modes other than read yet" if mode != "r" && !block_given?
39
+
40
+ content = read(file_name)
41
+ new_content = content.dup
42
+
43
+ io = StringIO.new(new_content)
44
+
45
+ if mode.start_with? "w"
46
+ io.truncate(0)
47
+ elsif mode.start_with? "a"
48
+ io.seek(0, IO::SEEK_END)
49
+ end
50
+
51
+ if block_given?
52
+ yield(io)
53
+
54
+ if (content != new_content) && !mode.start_with?("r")
55
+ __transport_connection.file(file_name).content = new_content # Need Train 2.5+
56
+ end
57
+ end
58
+
59
+ io
60
+ end
61
+
62
+ def readlines(file_name)
63
+ content = __transport_connection.file(file_name).content
64
+ raise Errno::ENOENT if content.nil? # Not found
65
+
66
+ content.split("\n")
67
+ end
68
+
69
+ ### START Could be in Train::File::...
70
+
71
+ def executable?(file_name)
72
+ mode(file_name) & 0111 != 0
73
+ end
74
+
75
+ def readable?(file_name)
76
+ cmd = format("test -r %s", file_name)
77
+ __transport_connection.run_command(cmd).exit_status == 0
78
+ end
79
+
80
+ def writable?(file_name)
81
+ cmd = format("test -w %s", file_name)
82
+ __transport_connection.run_command(cmd).exit_status == 0
83
+ end
84
+
85
+ # def ftype(file_name)
86
+ # case type(file_name)
87
+ # when :block_device
88
+ # "blockSpecial"
89
+ # when :character_device
90
+ # "characterSpecial"
91
+ # when :symlink
92
+ # "link"
93
+ # else
94
+ # type(file_name).to_s
95
+ # end
96
+ # end
97
+
98
+ def realpath(file_name)
99
+ cmd = "realpath #{file_name}" # coreutils, not MacOSX
100
+ Chef::Log.debug cmd
101
+
102
+ __transport_connection.run_command(cmd).stdout.chop
103
+ end
104
+
105
+ def readlink(file_name)
106
+ raise Errno::EINVAL unless symlink?(file_name)
107
+
108
+ cmd = "readlink #{file_name}"
109
+ Chef::Log.debug cmd
110
+
111
+ __transport_connection.run_command(cmd).stdout.chop
112
+ end
113
+
114
+ # def setgid?(file_name)
115
+ # mode(file_name) & 04000 != 0
116
+ # end
117
+
118
+ # def setuid?(file_name)
119
+ # mode(file_name) & 02000 != 0
120
+ # end
121
+
122
+ # def sticky?(file_name)
123
+ # mode(file_name) & 01000 != 0
124
+ # end
125
+
126
+ # def size?(file_name)
127
+ # exist?(file_name) && size(file_name) > 0
128
+ # end
129
+
130
+ # def world_readable?(file_name)
131
+ # mode(file_name) & 0001 != 0
132
+ # end
133
+
134
+ # def world_writable?(file_name)
135
+ # mode(file_name) & 0002 != 0
136
+ # end
137
+
138
+ # def zero?(file_name)
139
+ # exists?(file_name) && size(file_name) == 0
140
+ # end
141
+
142
+ ### END: Could be in Train
143
+
144
+ # passthrough or map calls to third parties
145
+ def method_missing(m, *args, **kwargs, &block)
146
+ nonio = %i{extname join dirname path split}
147
+
148
+ # TODO: writable?
149
+ passthru = %i{basename directory? exist? exists? file? path pipe? socket? symlink?}
150
+ redirect_train = {
151
+ blockdev?: :block_device?,
152
+ chardev?: :character_device?,
153
+ }
154
+ redirect_utils = {
155
+ chown: :chown,
156
+ chmod: :chmod,
157
+ symlink: :ln_s,
158
+ delete: :rm,
159
+ }
160
+ filestat = %i{gid group mode owner selinux_label size uid}
161
+
162
+ if %i{stat lstat}.include? m
163
+ Chef::Log.debug "File::#{m} passed to Train.file.stat"
164
+
165
+ follow_symlink = m == :stat
166
+ tfile = __transport_connection.file(args[0], follow_symlink).stat
167
+
168
+ require "ostruct" unless defined?(OpenStruct)
169
+ OpenStruct.new(tfile)
170
+
171
+ # Non-IO methods can be issued locally
172
+ elsif nonio.include? m
173
+ ::File.send(m, *args, **kwargs) # TODO: pass block
174
+
175
+ elsif passthru.include? m
176
+ Chef::Log.debug "File::#{m} passed to Train.file.#{m}"
177
+
178
+ file_name, other_args = args[0], args[1..]
179
+
180
+ file = __transport_connection.file(file_name)
181
+ file.send(m, *other_args, **kwargs) # block?
182
+
183
+ elsif m == :mtime
184
+ # Solve a data type disparity between Train.file and File
185
+ timestamp = __transport_connection.file(args[0]).mtime
186
+ Time.at(timestamp)
187
+
188
+ elsif filestat.include? m
189
+ Chef::Log.debug "File::#{m} passed to Train.file.stat.#{m}"
190
+
191
+ __transport_connection.file(args[0]).stat[m]
192
+
193
+ elsif redirect_utils.key?(m)
194
+ new_method = redirect_utils[m]
195
+ Chef::Log.debug "File::#{m} redirected to TargetIO::FileUtils.#{new_method}"
196
+
197
+ ::TargetIO::FileUtils.send(new_method, *args, **kwargs) # TODO: pass block
198
+
199
+ elsif redirect_train.key?(m)
200
+ new_method = redirect_train[m]
201
+ Chef::Log.debug "File::#{m} redirected to Train.file.#{new_method}"
202
+
203
+ file_name, other_args = args[0], args[1..]
204
+
205
+ file = __transport_connection.file(file_name)
206
+ file.send(redirect[m], *other_args, **kwargs) # TODO: pass block
207
+
208
+ else
209
+ raise "Unsupported File method #{m}"
210
+ end
211
+ end
212
+
213
+ def __transport_connection
214
+ Chef.run_context&.transport_connection
215
+ end
216
+ end
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,220 @@
1
+ module TargetIO
2
+ module TrainCompat
3
+ class FileUtils
4
+ class << self
5
+ def chmod(mode, list, noop: nil, verbose: nil)
6
+ cmd = sprintf("chmod %s %s", __mode_to_s(mode), Array(list).join(" "))
7
+
8
+ Chef::Log.debug cmd if verbose
9
+ return if noop
10
+
11
+ __run_command(cmd)
12
+ end
13
+
14
+ def chmod_R(mode, list, noop: nil, verbose: nil, force: nil)
15
+ cmd = sprintf("chmod -R%s %s %s", (force ? "f" : ""), mode_to_s(mode), Array(list).join(" "))
16
+
17
+ Chef::Log.debug cmd if verbose
18
+ return if noop
19
+
20
+ __run_command(cmd)
21
+ end
22
+
23
+ def chown(user, group, list, noop: nil, verbose: nil)
24
+ cmd = sprintf("chown %s %s", (group ? "#{user}:#{group}" : user || ":"), Array(list).join(" "))
25
+
26
+ Chef::Log.debug cmd if verbose
27
+ return if noop
28
+
29
+ __run_command(cmd)
30
+ end
31
+
32
+ def chown_R(user, group, list, noop: nil, verbose: nil, force: nil)
33
+ cmd = sprintf("chown -R%s %s %s", (force ? "f" : ""), (group ? "#{user}:#{group}" : user || ":"), Array(list).join(" "))
34
+
35
+ Chef::Log.debug cmd if verbose
36
+ return if noop
37
+
38
+ __run_command(cmd)
39
+ end
40
+
41
+ # cmp
42
+ # collect_method
43
+ # commands
44
+ # compare_file
45
+ # compare_stream
46
+
47
+ def cp(src, dest, preserve: nil, noop: nil, verbose: nil)
48
+ cmd = "cp#{preserve ? " -p" : ""} #{[src, dest].flatten.join(" ")}"
49
+
50
+ Chef::Log.debug cmd if verbose
51
+ return if noop
52
+
53
+ __run_command(cmd)
54
+ end
55
+ alias_method :copy, :cp
56
+
57
+ def cp_lr(src, dest, noop: nil, verbose: nil, dereference_root: true, remove_destination: false)
58
+ cmd = "cp -lr#{remove_destination ? " --remove-destination" : ""} #{[src, dest].flatten.join(" ")}"
59
+
60
+ Chef::Log.debug cmd if verbose
61
+ return if noop
62
+
63
+ __run_command(cmd)
64
+ end
65
+
66
+ def cp_r(src, dest, preserve: nil, noop: nil, verbose: nil, dereference_root: true, remove_destination: nil)
67
+ cmd = "cp -r#{preserve ? "p" : ""}#{remove_destination ? " --remove-destination" : ""} #{[src, dest].flatten.join(" ")}"
68
+
69
+ Chef::Log.debug cmd if verbose
70
+ return if noop
71
+
72
+ __run_command(cmd)
73
+ end
74
+
75
+ # getwd (alias pwd)
76
+ # have_option?
77
+ # identical? (alias compare_file)
78
+
79
+ def install(src, dest, mode: nil, owner: nil, group: nil, preserve: nil, noop: nil, verbose: nil)
80
+ cmd = "install -c"
81
+ cmd << " -p" if preserve
82
+ cmd << " -m " << mode_to_s(mode) if mode
83
+ cmd << " -o #{owner}" if owner
84
+ cmd << " -g #{group}" if group
85
+ cmd << " " << [src, dest].flatten.join(" ")
86
+
87
+ Chef::Log.debug cmd if verbose
88
+ return if noop
89
+
90
+ __run_command(cmd)
91
+ end
92
+
93
+ def ln(src, dest, force: nil, noop: nil, verbose: nil)
94
+ cmd = "ln#{force ? " -f" : ""} #{[src, dest].flatten.join(" ")}"
95
+
96
+ Chef::Log.debug cmd if verbose
97
+ return if noop
98
+
99
+ __run_command(cmd)
100
+ end
101
+ alias_method :link, :ln
102
+
103
+ def ln_s(src, dest, force: nil, noop: nil, verbose: nil)
104
+ cmd = "ln -s#{force ? "f" : ""} #{[src, dest].flatten.join(" ")}"
105
+
106
+ Chef::Log.debug cmd if verbose
107
+ return if noop
108
+
109
+ __run_command(cmd)
110
+ end
111
+ alias_method :symlink, :ln_s
112
+
113
+ def ln_sf(src, dest, noop: nil, verbose: nil)
114
+ ln_s(src, dest, force: true, noop: noop, verbose: verbose)
115
+ end
116
+
117
+ def mkdir(list, mode: nil, noop: nil, verbose: nil)
118
+ cmd = "mkdir #{mode ? ("-m %03o " % mode) : ""}#{Array(list).join(" ")}"
119
+
120
+ Chef::Log.debug cmd if verbose
121
+ return if noop
122
+
123
+ __run_command(cmd)
124
+ end
125
+
126
+ def mkdir_p(list, mode: nil, noop: nil, verbose: nil)
127
+ cmd = "mkdir -p #{mode ? ("-m %03o " % mode) : ""}#{Array(list).join(" ")}"
128
+
129
+ Chef::Log.debug cmd if verbose
130
+ return if noop
131
+
132
+ __run_command(cmd)
133
+ end
134
+ alias_method :makedirs, :mkdir_p
135
+ alias_method :mkpath, :mkdir_p
136
+
137
+ def mv(src, dest, force: nil, noop: nil, verbose: nil, secure: nil)
138
+ cmd = "mv#{force ? " -f" : ""} #{[src, dest].flatten.join(" ")}"
139
+
140
+ Chef::Log.debug cmd if verbose
141
+ return if noop
142
+
143
+ __run_command(cmd)
144
+ end
145
+
146
+ # options
147
+ # options_of
148
+ # pwd
149
+ # remove
150
+ # remove_entry_secure
151
+ # remove_file
152
+
153
+ def rm(list, force: nil, noop: nil, verbose: nil)
154
+ cmd = "rm#{force ? " -f" : ""} #{Array(list).join(" ")}"
155
+
156
+ Chef::Log.debug cmd if verbose
157
+ return if noop
158
+
159
+ __run_command(cmd)
160
+ end
161
+
162
+ def rm_f(list, force: nil, noop: nil, verbose: nil, secure: nil)
163
+ rm(list, force: true, noop: noop, verbose: verbose)
164
+ end
165
+
166
+ def rm_r(list, force: nil, noop: nil, verbose: nil, secure: nil)
167
+ cmd = "rm -r#{force ? "f" : ""} #{Array(list).join(" ")}"
168
+
169
+ Chef::Log.debug cmd if verbose
170
+ return if noop
171
+
172
+ __run_command(cmd)
173
+ end
174
+
175
+ def rm_rf(list, noop: nil, verbose: nil, secure: nil)
176
+ rm_r(list, force: true, noop: noop, verbose: verbose, secure: secure)
177
+ end
178
+ alias_method :remove_entry, :rm_rf
179
+ alias_method :rmtree, :rm_rf
180
+ alias_method :safe_unlink, :rm_rf
181
+
182
+ def rmdir(list, parents: nil, noop: nil, verbose: nil)
183
+ cmd = "rmdir #{parents ? "-p " : ""}#{Array(list).join(" ")}"
184
+
185
+ Chef::Log.debug cmd if verbose
186
+ return if noop
187
+
188
+ __run_command(cmd)
189
+ end
190
+
191
+ def touch(list, noop: nil, verbose: nil, mtime: nil, nocreate: nil)
192
+ return if noop
193
+
194
+ __run_command "touch #{nocreate ? "-c " : ""}#{mtime ? mtime.strftime("-t %Y%m%d%H%M.%S ") : ""}#{Array(list).join(" ")}"
195
+ end
196
+
197
+ # uptodate?
198
+
199
+ def method_missing(m, *_args, **_kwargs, &_block)
200
+ raise "Unsupported #{self.class} method #{m}"
201
+ end
202
+
203
+ private
204
+
205
+ # TODO: Symbolic modes
206
+ def __mode_to_s(mode)
207
+ mode.to_s(8)
208
+ end
209
+
210
+ def __run_command(cmd)
211
+ __transport_connection.run_command(cmd)
212
+ end
213
+
214
+ def __transport_connection
215
+ Chef.run_context&.transport_connection
216
+ end
217
+ end
218
+ end
219
+ end
220
+ end