chef 18.4.2 → 18.5.0

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