kanrisuru 0.9.2 → 0.12.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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CONTRIBUTING.md +9 -9
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +7 -8
  4. data/.rspec +1 -1
  5. data/CHANGELOG.md +125 -96
  6. data/CODE_OF_CONDUCT.md +10 -10
  7. data/README.md +19 -90
  8. data/kanrisuru.gemspec +2 -1
  9. data/lib/kanrisuru/command.rb +7 -0
  10. data/lib/kanrisuru/core/archive.rb +13 -36
  11. data/lib/kanrisuru/core/disk.rb +0 -3
  12. data/lib/kanrisuru/core/dmi.rb +1 -1
  13. data/lib/kanrisuru/core/file.rb +4 -11
  14. data/lib/kanrisuru/core/find.rb +6 -11
  15. data/lib/kanrisuru/core/mount.rb +14 -15
  16. data/lib/kanrisuru/core/socket.rb +2 -1
  17. data/lib/kanrisuru/core/stream.rb +1 -2
  18. data/lib/kanrisuru/core/zypper.rb +6 -23
  19. data/lib/kanrisuru/os_package/collection.rb +58 -0
  20. data/lib/kanrisuru/os_package/define.rb +34 -0
  21. data/lib/kanrisuru/os_package/include.rb +163 -0
  22. data/lib/kanrisuru/os_package.rb +3 -245
  23. data/lib/kanrisuru/remote/cpu.rb +5 -1
  24. data/lib/kanrisuru/remote/env.rb +8 -0
  25. data/lib/kanrisuru/remote/fstab.rb +5 -5
  26. data/lib/kanrisuru/result.rb +5 -4
  27. data/lib/kanrisuru/util.rb +1 -1
  28. data/lib/kanrisuru/version.rb +1 -1
  29. data/spec/functional/core/apt_spec.rb +22 -30
  30. data/spec/functional/core/archive_spec.rb +170 -0
  31. data/spec/functional/core/find_spec.rb +94 -113
  32. data/spec/functional/core/mount_spec.rb +121 -0
  33. data/spec/functional/core/socket_spec.rb +23 -28
  34. data/spec/functional/core/stream_spec.rb +12 -12
  35. data/spec/functional/core/transfer_spec.rb +108 -131
  36. data/spec/functional/core/yum_spec.rb +58 -83
  37. data/spec/functional/remote/cluster_spec.rb +11 -2
  38. data/spec/functional/remote/cpu_spec.rb +104 -0
  39. data/spec/functional/remote/env_spec.rb +48 -0
  40. data/spec/helper/stub_network.rb +49 -14
  41. data/spec/helper/test_hosts.rb +11 -1
  42. data/spec/integration/core/apt_spec.rb +2 -3
  43. data/spec/integration/core/archive_spec.rb +8 -13
  44. data/spec/integration/core/disk_spec.rb +2 -3
  45. data/spec/integration/core/dmi_spec.rb +2 -3
  46. data/spec/integration/core/file_spec.rb +4 -14
  47. data/spec/integration/core/find_spec.rb +3 -3
  48. data/spec/integration/core/group_spec.rb +2 -3
  49. data/spec/integration/core/ip_spec.rb +2 -3
  50. data/spec/integration/core/path_spec.rb +2 -3
  51. data/spec/integration/core/socket_spec.rb +2 -4
  52. data/spec/integration/core/stat_spec.rb +2 -3
  53. data/spec/integration/core/stream_spec.rb +6 -9
  54. data/spec/integration/core/system_spec.rb +2 -4
  55. data/spec/integration/core/transfer_spec.rb +4 -9
  56. data/spec/integration/core/user_spec.rb +2 -4
  57. data/spec/integration/core/yum_spec.rb +2 -3
  58. data/spec/integration/core/zypper_spec.rb +5 -6
  59. data/spec/{functional → integration}/os_package_spec.rb +0 -0
  60. data/spec/integration/remote/cpu_spec.rb +2 -3
  61. data/spec/integration/remote/env_spec.rb +2 -3
  62. data/spec/integration/remote/fstab_spec.rb +2 -3
  63. data/spec/integration/remote/host_spec.rb +2 -3
  64. data/spec/integration/remote/memory_spec.rb +2 -2
  65. data/spec/integration/remote/os_spec.rb +2 -3
  66. data/spec/integration/remote/remote_file_spec.rb +9 -15
  67. data/spec/spec_helper.rb +12 -3
  68. data/spec/unit/command_spec.rb +49 -0
  69. data/spec/unit/core/find_spec.rb +1 -1
  70. data/spec/unit/core/yum_spec.rb +1 -1
  71. data/spec/unit/mode_spec.rb +33 -2
  72. data/spec/unit/remote/cluster_spec.rb +3 -1
  73. data/spec/unit/remote/cpu_spec.rb +1 -2
  74. data/spec/unit/remote/env_spec.rb +17 -0
  75. data/spec/unit/util_spec.rb +13 -0
  76. metadata +28 -5
@@ -10,18 +10,16 @@ module Kanrisuru
10
10
  FilePath = Struct.new(:path)
11
11
 
12
12
  def tar(action, file, opts = {})
13
- compress = opts[:compress]
14
13
  paths = opts[:paths]
15
14
  exclude = opts[:exclude]
16
- directory = opts[:directory]
17
15
 
18
16
  command = Kanrisuru::Command.new('tar --restrict')
19
17
 
20
- directory = realpath(directory, strip: true).path if directory
18
+ directory = opts[:directory] ? realpath(opts[:directory], strip: true).path : nil
21
19
  command.append_arg('-C', directory)
22
20
  command.append_arg('-f', file)
23
21
 
24
- set_compression(command, compress) if compress
22
+ set_compression(command, opts[:compress]) if opts[:compress]
25
23
 
26
24
  case action
27
25
  when 'list', 't'
@@ -50,7 +48,7 @@ module Kanrisuru
50
48
  command.append_flag('--same-owner', opts[:same_owners])
51
49
  command.append_flag('--multi-volume', opts[:multi_volume])
52
50
  command.append_flag('--label', opts[:label])
53
- command.append_flag('--one-file-system ', opts[:one_file_system])
51
+ command.append_flag('--one-file-system', opts[:one_file_system])
54
52
  command.append_flag('--keep-old-files', opts[:keep_old_files])
55
53
  command.append_flag('--skip-old-files', opts[:skip_old_files])
56
54
  command.append_flag('--overwrite', opts[:overwrite])
@@ -58,10 +56,7 @@ module Kanrisuru
58
56
  command.append_flag('--unlink-first', opts[:unlink_first])
59
57
  command.append_flag('--recursive-unlink', opts[:recursive_unlink])
60
58
 
61
- if Kanrisuru::Util.present?(paths)
62
- paths = paths.instance_of(String) ? [paths] : paths
63
- command << paths.join(' ')
64
- end
59
+ command.append_array(paths)
65
60
 
66
61
  execute_shell(command)
67
62
  Kanrisuru::Result.new(command)
@@ -70,45 +65,31 @@ module Kanrisuru
70
65
  command.append_flag('--multi-volume', opts[:multi_volume])
71
66
 
72
67
  if Kanrisuru::Util.present?(exclude)
73
- exclude = exclude.instance_of?(String) ? [exclude] : exclude
74
- command.append_arg('--exclude', exclude.join(' '))
68
+ options = exclude.instance_of?(String) ? [exclude] : exclude
69
+ options.each do |option|
70
+ command << "--exclude=#{option}"
71
+ end
75
72
  end
76
73
 
77
- if Kanrisuru::Util.present?(paths)
78
- paths = paths.instance_of?(String) ? [paths] : paths
79
- command << paths.join(' ')
80
- end
74
+ command.append_array(paths)
81
75
 
82
76
  execute_shell(command)
83
-
84
77
  Kanrisuru::Result.new(command)
85
78
  when 'append', 'r'
86
79
  command.append_flag('-r')
87
-
88
- if Kanrisuru::Util.present?(paths)
89
- paths = paths.instance_of?(String) ? [paths] : paths
90
- command << paths.join(' ')
91
- end
80
+ command.append_array(paths)
92
81
 
93
82
  execute_shell(command)
94
83
  Kanrisuru::Result.new(command)
95
84
  when 'catenate', 'concat', 'A'
96
85
  command.append_flag('-A')
97
-
98
- if Kanrisuru::Util.present?(paths)
99
- paths = paths.instance_of?(String) ? [paths] : paths
100
- command << paths.join(' ')
101
- end
86
+ command.append_array(paths)
102
87
 
103
88
  execute_shell(command)
104
89
  Kanrisuru::Result.new(command)
105
90
  when 'update', 'u'
106
91
  command.append_flag('-u')
107
-
108
- if Kanrisuru::Util.present?(paths)
109
- paths = paths.instance_of?(String) ? [paths] : paths
110
- command << paths.join(' ')
111
- end
92
+ command.append_array(paths)
112
93
 
113
94
  execute_shell(command)
114
95
  Kanrisuru::Result.new(command)
@@ -121,11 +102,7 @@ module Kanrisuru
121
102
  when 'delete'
122
103
  command.append_flag('--delete')
123
104
  command.append_arg('--occurrence', opts[:occurrence])
124
-
125
- if Kanrisuru::Util.present?(paths)
126
- paths = paths.instance_of?(String) ? [paths] : paths
127
- command << paths.join(' ')
128
- end
105
+ command.append_array(paths)
129
106
 
130
107
  execute_shell(command)
131
108
  Kanrisuru::Result.new(command)
@@ -113,9 +113,6 @@ module Kanrisuru
113
113
  case mode
114
114
  when 'search'
115
115
  cmd.to_s
116
- when 'device'
117
- lines = cmd.to_a
118
- blkid_devices(lines)
119
116
  else
120
117
  lines = cmd.to_a
121
118
  blkid_devices(lines)
@@ -511,7 +511,7 @@ module Kanrisuru
511
511
  return unless Kanrisuru::Util.present?(opts[:types])
512
512
 
513
513
  types = opts[:types]
514
- types = types.instance_of?(Array) ? types : [types]
514
+ types = [types] if types.instance_of?(String)
515
515
 
516
516
  types.each do |type|
517
517
  type = parse_dmi_type(type)
@@ -64,12 +64,9 @@ module Kanrisuru
64
64
  command << dest
65
65
  elsif opts[:target_directory]
66
66
  command.append_arg('-t', dest)
67
-
68
- source = source.instance_of?(String) ? [source] : source
69
- command << source.join(' ')
67
+ command.append_array(source)
70
68
  else
71
- source = source.instance_of?(String) ? [source] : source
72
- command << source.join(' ')
69
+ command.append_array(source)
73
70
  command << dest
74
71
  end
75
72
 
@@ -108,13 +105,9 @@ module Kanrisuru
108
105
  command << dest
109
106
  elsif opts[:target_directory]
110
107
  command.append_arg('-t', dest)
111
-
112
- source = source.instance_of?(String) ? [source] : source
113
- command << source.join(' ')
108
+ command.append_array(source)
114
109
  else
115
- source = source.instance_of?(String) ? [source] : source
116
-
117
- command << source.join(' ')
110
+ command.append_array(source)
118
111
  command << dest
119
112
  end
120
113
 
@@ -10,7 +10,7 @@ module Kanrisuru
10
10
  os_define :linux, :find
11
11
 
12
12
  FilePath = Struct.new(:path)
13
- REGEX_TYPES = ['emacs', 'posix-awk', 'posix-basic', 'posix-egrep', 'posix-extended']
13
+ REGEX_TYPES = %w[emacs posix-awk posix-basic posix-egrep posix-extended].freeze
14
14
 
15
15
  def find(opts = {})
16
16
  paths = opts[:paths]
@@ -30,13 +30,9 @@ module Kanrisuru
30
30
  end
31
31
 
32
32
  if Kanrisuru::Util.present?(paths)
33
- if paths.instance_of?(Array)
34
- paths = paths.join(' ')
35
- elsif paths.class != String
36
- raise ArgumentError, 'Invalid paths type'
37
- end
33
+ raise ArgumentError, 'Invalid paths type' unless [String, Array].include?(paths.class)
38
34
 
39
- command << paths
35
+ command.append_array(paths)
40
36
  end
41
37
 
42
38
  command.append_flag('-executable', opts[:executable])
@@ -66,9 +62,7 @@ module Kanrisuru
66
62
  command.append_arg('-mmin', opts[:mmin])
67
63
 
68
64
  if Kanrisuru::Util.present?(opts[:regex_type])
69
- unless REGEX_TYPES.include?(opts[:regex_type])
70
- raise ArgumentError, 'invalid regex type'
71
- end
65
+ raise ArgumentError, 'invalid regex type' unless REGEX_TYPES.include?(opts[:regex_type])
72
66
 
73
67
  command.append_arg('-regextype', opts[:regex_type])
74
68
  end
@@ -77,7 +71,8 @@ module Kanrisuru
77
71
 
78
72
  if size.instance_of?(String)
79
73
  regex = Regexp.new(/^([-+])?(\d+)([bcwkMG])*$/)
80
- raise ArgumentError, "invalid size string: '#{@size}'" unless regex.match?(size)
74
+ raise ArgumentError, "invalid size string: '#{@size}'" unless regex.match?(size)
75
+
81
76
  command.append_arg('-size', size)
82
77
  elsif size.instance_of?(Integer)
83
78
  command.append_arg('-size', size)
@@ -10,9 +10,6 @@ module Kanrisuru
10
10
 
11
11
  def mount(opts = {})
12
12
  type = opts[:type]
13
- all = opts[:all]
14
- device = opts[:device]
15
- directory = opts[:directory]
16
13
 
17
14
  bind_old = opts[:bind_old]
18
15
  bind_new = opts[:bind_new]
@@ -39,13 +36,12 @@ module Kanrisuru
39
36
  else
40
37
  command.append_arg('-L', opts[:label])
41
38
  command.append_arg('-U', opts[:uuid])
42
- command.append_flag('-n', opts[:no_mtab])
43
39
  command.append_flag('-f', opts[:fake])
44
40
  command.append_flag('-i', opts[:internal_only])
45
41
  command.append_flag('-s', opts[:sloppy])
46
42
 
47
43
  command.append_flag('--no-mtab', opts[:no_mtab])
48
- command.append_flag('--no-canonicalizeb', opts[:no_canonicalize])
44
+ command.append_flag('--no-canonicalize', opts[:no_canonicalize])
49
45
 
50
46
  fs_options = nil
51
47
  if Kanrisuru::Util.present?(type)
@@ -55,14 +51,14 @@ module Kanrisuru
55
51
  fs_options = Kanrisuru::Remote::Fstab::Options.new('common', fs_opts)
56
52
  end
57
53
 
58
- if Kanrisuru::Util.present?(all)
54
+ if Kanrisuru::Util.present?(opts[:all])
59
55
  command.append_flag('-a')
60
56
  add_test_opts(command, opts[:test_opts], type)
61
57
  else
62
58
  command.append_arg('-o', fs_options.to_s)
63
59
 
64
- command << device if Kanrisuru::Util.present?(device)
65
- command << directory if Kanrisuru::Util.present?(directory)
60
+ command << opts[:device] if Kanrisuru::Util.present?(opts[:device])
61
+ command << opts[:directory] if Kanrisuru::Util.present?(opts[:directory])
66
62
  end
67
63
  end
68
64
 
@@ -75,12 +71,6 @@ module Kanrisuru
75
71
  type = opts[:type]
76
72
  command = Kanrisuru::Command.new('umount')
77
73
 
78
- if Kanrisuru::Util.present?(all)
79
- command.append_flag('-a')
80
- add_type(command, type)
81
- add_test_opts(command, opts[:test_opts], type)
82
- end
83
-
84
74
  command.append_flag('--fake', opts[:fake])
85
75
  command.append_flag('--no-canonicalize', opts[:no_canonicalize])
86
76
  command.append_flag('-n', opts[:no_mtab])
@@ -90,6 +80,15 @@ module Kanrisuru
90
80
  command.append_flag('-l', opts[:lazy])
91
81
  command.append_flag('-f', opts[:force])
92
82
 
83
+ if Kanrisuru::Util.present?(all)
84
+ command.append_flag('-a')
85
+ add_type(command, type)
86
+ add_test_opts(command, opts[:test_opts], type)
87
+ else
88
+ command << opts[:device] if Kanrisuru::Util.present?(opts[:device])
89
+ command << opts[:directory] if Kanrisuru::Util.present?(opts[:directory])
90
+ end
91
+
93
92
  execute_shell(command)
94
93
 
95
94
  Kanrisuru::Result.new(command)
@@ -115,7 +114,7 @@ module Kanrisuru
115
114
 
116
115
  test_types.each do |t|
117
116
  device_opts = Kanrisuru::Util::FsMountOpts.get_device(t)
118
- raise ArugmentError, "Invalid fstype: #{t}" unless device_opts
117
+ raise ArgumentError, "Invalid fstype: #{t}" unless device_opts
119
118
  end
120
119
 
121
120
  command.append_arg('-t', type)
@@ -59,7 +59,8 @@ module Kanrisuru
59
59
  command.append_flag('-w', opts[:raw])
60
60
 
61
61
  if Kanrisuru::Util.present?(family)
62
- raise ArgumentError, 'invalid family type' if !NETWORK_FAMILIES.include?(family)
62
+ raise ArgumentError, 'invalid family type' unless NETWORK_FAMILIES.include?(family)
63
+
63
64
  command.append_arg('-f', family)
64
65
  end
65
66
 
@@ -95,8 +95,7 @@ module Kanrisuru
95
95
  command.append_flag('-b', opts[:number_nonblank])
96
96
  command.append_flag('-A', opts[:show_all])
97
97
 
98
- files = files.instance_of?(String) ? [files] : files
99
- command << files.join(' ')
98
+ command.append_array(files)
100
99
 
101
100
  append_file(command, opts)
102
101
  execute_shell(command)
@@ -181,8 +181,7 @@ module Kanrisuru
181
181
  command.append_flag('--metadata', opts[:metadata])
182
182
  command.append_flag('--raw-metadata', opts[:raw_metadata])
183
183
  command.append_flag('--all', opts[:all])
184
-
185
- command << opts[:repos]
184
+ command.append_array(opts[:repos])
186
185
 
187
186
  execute_shell(command)
188
187
 
@@ -276,11 +275,7 @@ module Kanrisuru
276
275
  command.append_arg('--medium-type', opts[:medium_type])
277
276
  end
278
277
 
279
- repos = opts[:repos]
280
- if Kanrisuru::Util.present?(repos)
281
- repos = repos.instance_of?(String) ? [repos] : repos
282
- command << repos.join(' ')
283
- end
278
+ command.append_array(opts[:repos])
284
279
 
285
280
  execute_shell(command)
286
281
 
@@ -336,11 +331,7 @@ module Kanrisuru
336
331
  command.append_arg('--media-type', opts[:media_type])
337
332
  end
338
333
 
339
- repos = opts[:repos]
340
- if Kanrisuru::Util.present?(repos)
341
- repos = repos.instance_of?(String) ? [repos] : repos
342
- command << repos.join(' ')
343
- end
334
+ command.append_array(opts[:repos])
344
335
 
345
336
  execute_shell(command)
346
337
 
@@ -372,11 +363,7 @@ module Kanrisuru
372
363
  command.append_flag('--refresh', opts[:refresh])
373
364
  command.append_flag('--no-refresh', opts[:no_refresh])
374
365
 
375
- services = opts[:services]
376
- if Kanrisuru::Util.present?(services)
377
- services = services.instance_of?(Array) ? services : [services]
378
- command << services.join(' ')
379
- end
366
+ command.append_array(opts[:services])
380
367
 
381
368
  execute_shell(command)
382
369
 
@@ -386,15 +373,11 @@ module Kanrisuru
386
373
  def zypper_remove_service(opts)
387
374
  command = Kanrisuru::Command.new('zypper')
388
375
  zypper_global_opts(command, opts)
376
+
389
377
  command << 'removeservice'
390
378
  command.append_flag('--loose-auth', opts[:loose_auth])
391
379
  command.append_flag('--loose-query', opts[:loose_query])
392
-
393
- services = opts[:services]
394
- if Kanrisuru::Util.present?(services)
395
- services = services.instance_of?(String) ? [services] : services
396
- command << services.join(' ')
397
- end
380
+ command.append_array(opts[:services])
398
381
 
399
382
  execute_shell(command)
400
383
 
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kanrisuru
4
+ module OsPackage
5
+ module Collection
6
+ def os_collection(mod, opts = {})
7
+ os_method_properties = mod.instance_variable_get(:@os_method_properties)
8
+ os_method_names = os_method_properties.keys
9
+
10
+ namespace = opts[:namespace]
11
+ namespace_instance = nil
12
+
13
+ if namespace
14
+ ## Define the namespace as an eigen class instance on the host.
15
+ ## Namespaced instances will access core host methods
16
+ ## with @host instance variable.
17
+
18
+ if Kanrisuru::Remote::Cluster.instance_variable_defined?("@#{namespace}")
19
+ namespace_class = Kanrisuru::Remote::Cluster.const_get(Kanrisuru::Util.camelize(namespace))
20
+ namespace_instance = instance_variable_get("@#{namespace}")
21
+ else
22
+ namespace_class = Kanrisuru::Remote::Cluster.const_set(Kanrisuru::Util.camelize(namespace), Class.new)
23
+ namespace_instance = Kanrisuru::Remote::Cluster.instance_variable_set("@#{namespace}", namespace_class.new)
24
+
25
+ class_eval do
26
+ define_method namespace do
27
+ namespace_instance.instance_variable_set(:@cluster, self)
28
+ namespace_instance
29
+ end
30
+ end
31
+ end
32
+
33
+ namespace_class.class_eval do
34
+ os_method_names.each do |method_name|
35
+ define_method method_name do |*args, &block|
36
+ cluster = namespace_instance.instance_variable_get(:@cluster)
37
+ hosts = cluster.instance_variable_get(:@hosts)
38
+ hosts.map do |host_addr, host|
39
+ { host: host_addr, result: host.send(namespace).send(method_name, *args, &block) }
40
+ end
41
+ end
42
+ end
43
+ end
44
+ else
45
+ class_eval do
46
+ os_method_names.each do |method_name|
47
+ define_method method_name do |*args, &block|
48
+ @hosts.map do |host_addr, host|
49
+ { host: host_addr, result: host.send(method_name, *args, &block) }
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kanrisuru
4
+ module OsPackage
5
+ module Define
6
+ def self.extended(base)
7
+ base.instance_variable_set(:@os_method_properties, {})
8
+ base.instance_variable_set(:@os_methods, Set.new)
9
+ end
10
+
11
+ def os_define(os_name, method_name, options = {})
12
+ unique_method_name = options[:alias] || method_name
13
+
14
+ @os_methods.add(method_name)
15
+
16
+ if @os_method_properties.key?(unique_method_name)
17
+ params = {
18
+ os_name: os_name.to_s,
19
+ method_name: method_name,
20
+ options: options
21
+ }
22
+
23
+ @os_method_properties[unique_method_name].prepend(params)
24
+ else
25
+ @os_method_properties[unique_method_name] = [{
26
+ os_name: os_name.to_s,
27
+ method_name: method_name,
28
+ options: options
29
+ }]
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,163 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kanrisuru
4
+ module OsPackage
5
+ module Include
6
+ def os_include(mod, opts = {})
7
+ os_method_properties = mod.instance_variable_get(:@os_method_properties)
8
+ os_method_names = os_method_properties.keys
9
+
10
+ ## Need to encapsulate any helper methods called in the module
11
+ ## to bind to the host instance. This acts as a psudeo module include.
12
+ os_methods = mod.instance_variable_get(:@os_methods)
13
+
14
+ public_methods = mod.instance_methods(false) - os_methods.to_a
15
+ private_methods = mod.private_instance_methods(false)
16
+ protected_methods = mod.protected_instance_methods(false)
17
+ include_methods = (public_methods + protected_methods + private_methods).flatten
18
+
19
+ include_method_bindings = proc do
20
+ include_methods.each do |method_name|
21
+ define_method method_name do |*args, &block|
22
+ unbound_method = mod.instance_method(method_name)
23
+ bind_method(unbound_method, *args, &block)
24
+ end
25
+ end
26
+
27
+ private_methods.each { |method_name| private(method_name) }
28
+ protected_methods.each { |method_name| protected(method_name) }
29
+
30
+ private
31
+ if RUBY_VERSION < '2.7'
32
+ define_method 'bind_method' do |unbound_method, *args, &block|
33
+ unbound_method.bind(self).call(*args, &block)
34
+ end
35
+ else
36
+ define_method 'bind_method' do |unbound_method, *args, &block|
37
+ unbound_method.bind_call(self, *args, &block)
38
+ end
39
+ end
40
+ end
41
+
42
+ namespace = opts[:namespace]
43
+ namespace_class = nil
44
+ namespace_instance = nil
45
+
46
+ if namespace
47
+ ## Define the namespace as an eigen class instance within the host class.
48
+ ## Namespaced instances will access core host methods
49
+ ## with @host instance variable.
50
+
51
+ ## Check to see if the namespace was defined. If so, additional methods will be appended to the
52
+ ## existing namespace class definition, otherwise, a new namespace class and instance will be
53
+ ## defined with the methods added.
54
+ if Kanrisuru::Remote::Host.instance_variable_defined?("@#{namespace}")
55
+ namespace_class = Kanrisuru::Remote::Host.const_get(Kanrisuru::Util.camelize(namespace))
56
+ namespace_instance = Kanrisuru::Remote::Host.instance_variable_get("@#{namespace}")
57
+ else
58
+ namespace_class = Kanrisuru::Remote::Host.const_set(Kanrisuru::Util.camelize(namespace), Class.new)
59
+ namespace_instance = Kanrisuru::Remote::Host.instance_variable_set("@#{namespace}", namespace_class.new)
60
+
61
+ class_eval do
62
+ define_method namespace do
63
+ namespace_instance.instance_variable_set(:@host, self)
64
+ namespace_instance
65
+ end
66
+ end
67
+ end
68
+
69
+ namespace_class.class_eval(&include_method_bindings)
70
+ else
71
+ class_eval(&include_method_bindings)
72
+ end
73
+
74
+ class_eval do
75
+ os_method_names.each do |method_name|
76
+ if namespace
77
+ namespace_class.class_eval do
78
+ define_method method_name do |*args, &block|
79
+ unbound_method = nil
80
+
81
+ host = namespace_instance.instance_variable_get(:@host)
82
+ os_method_cache = host.instance_variable_get(:@os_method_cache) || {}
83
+
84
+ if os_method_cache.key?("#{namespace}.#{method_name}")
85
+ unbound_method = os_method_cache["#{namespace}.#{method_name}"]
86
+ else
87
+ ## Find the correct method to resolve based on the OS for the remote host.
88
+ defined_method_name = host.resolve_os_method_name(os_method_properties, method_name)
89
+ unless defined_method_name
90
+ raise NoMethodError, "undefined method `#{method_name}' for #{self.class}"
91
+ end
92
+
93
+ ## Get reference to the unbound method defined in module
94
+ unbound_method = mod.instance_method(defined_method_name)
95
+ raise NoMethodError, "undefined method `#{method_name}' for #{self.class}" unless unbound_method
96
+
97
+ ## Cache the unbound method on this host instance for faster resolution on
98
+ ## the next invocation of this method
99
+ os_method_cache["#{namespace}.#{method_name}"] = unbound_method
100
+ host.instance_variable_set(:@os_method_cache, os_method_cache)
101
+ end
102
+
103
+ ## Bind the method to host instance and
104
+ ## call it with args and block
105
+ bind_method(unbound_method, *args, &block)
106
+ end
107
+ end
108
+ else
109
+ define_method method_name do |*args, &block|
110
+ unbound_method = nil
111
+
112
+ host = self
113
+ os_method_cache = host.instance_variable_get(:@os_method_cache) || {}
114
+
115
+ if os_method_cache.key?(method_name)
116
+ unbound_method = os_method_cache[method_name]
117
+ else
118
+ ## Find the correct method to resolve based on the OS for the remote host.
119
+ defined_method_name = host.resolve_os_method_name(os_method_properties, method_name)
120
+ raise NoMethodError, "undefined method `#{method_name}' for #{self.class}" unless defined_method_name
121
+
122
+ ## Get reference to the unbound method defined in module
123
+ unbound_method = mod.instance_method(defined_method_name)
124
+ raise NoMethodError, "undefined method `#{method_name}' for #{self.class}" unless unbound_method
125
+
126
+ ## Cache the unbound method on this host instance for faster resolution on
127
+ ## the next invocation of this method
128
+ os_method_cache[method_name] = unbound_method
129
+ host.instance_variable_set(:@os_method_cache, os_method_cache)
130
+ end
131
+
132
+ ## Bind the method to host instance and
133
+ ## call it with args and block
134
+ bind_method(unbound_method, *args, &block)
135
+ end
136
+ end
137
+ end
138
+
139
+ def resolve_os_method_name(properties, method_name)
140
+ kernel = os.kernel.downcase
141
+ release = os.release.downcase
142
+
143
+ properties[method_name].each do |property|
144
+ os_name = property[:os_name]
145
+ strict = property[:options] ? property[:options][:strict] : false
146
+ except = property[:options] ? property[:options][:except] : ''
147
+
148
+ next if except && (except == release || except.include?(release))
149
+
150
+ if release == os_name || kernel == os_name ||
151
+ (Kanrisuru::Util::OsFamily.family_include_distribution?(os_name, release) && !strict) ||
152
+ (Kanrisuru::Util::OsFamily.upstream_include_distribution?(os_name, release) && !strict)
153
+ return property[:method_name]
154
+ end
155
+ end
156
+
157
+ nil
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end