kanrisuru 0.10.0 → 0.12.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) 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 +127 -102
  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 +11 -35
  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/fstab.rb +5 -5
  25. data/lib/kanrisuru/result.rb +5 -4
  26. data/lib/kanrisuru/util.rb +1 -1
  27. data/lib/kanrisuru/version.rb +1 -1
  28. data/spec/functional/core/apt_spec.rb +22 -30
  29. data/spec/functional/core/archive_spec.rb +96 -120
  30. data/spec/functional/core/find_spec.rb +94 -113
  31. data/spec/functional/core/mount_spec.rb +121 -0
  32. data/spec/functional/core/socket_spec.rb +23 -28
  33. data/spec/functional/core/stream_spec.rb +12 -12
  34. data/spec/functional/core/transfer_spec.rb +108 -131
  35. data/spec/functional/core/yum_spec.rb +58 -83
  36. data/spec/functional/remote/cluster_spec.rb +11 -2
  37. data/spec/functional/remote/cpu_spec.rb +104 -0
  38. data/spec/functional/remote/env_spec.rb +3 -5
  39. data/spec/helper/stub_network.rb +35 -16
  40. data/spec/helper/test_hosts.rb +11 -1
  41. data/spec/integration/core/apt_spec.rb +2 -3
  42. data/spec/integration/core/archive_spec.rb +8 -13
  43. data/spec/integration/core/disk_spec.rb +2 -3
  44. data/spec/integration/core/dmi_spec.rb +2 -3
  45. data/spec/integration/core/file_spec.rb +4 -14
  46. data/spec/integration/core/find_spec.rb +3 -3
  47. data/spec/integration/core/group_spec.rb +2 -3
  48. data/spec/integration/core/ip_spec.rb +2 -3
  49. data/spec/integration/core/path_spec.rb +2 -3
  50. data/spec/integration/core/socket_spec.rb +2 -4
  51. data/spec/integration/core/stat_spec.rb +2 -3
  52. data/spec/integration/core/stream_spec.rb +6 -9
  53. data/spec/integration/core/system_spec.rb +2 -4
  54. data/spec/integration/core/transfer_spec.rb +4 -9
  55. data/spec/integration/core/user_spec.rb +2 -4
  56. data/spec/integration/core/yum_spec.rb +2 -3
  57. data/spec/integration/core/zypper_spec.rb +5 -6
  58. data/spec/integration/remote/cpu_spec.rb +2 -3
  59. data/spec/integration/remote/env_spec.rb +2 -3
  60. data/spec/integration/remote/fstab_spec.rb +2 -3
  61. data/spec/integration/remote/host_spec.rb +2 -3
  62. data/spec/integration/remote/memory_spec.rb +2 -2
  63. data/spec/integration/remote/os_spec.rb +2 -3
  64. data/spec/integration/remote/remote_file_spec.rb +9 -15
  65. data/spec/spec_helper.rb +12 -3
  66. data/spec/unit/command_spec.rb +19 -1
  67. data/spec/unit/core/find_spec.rb +1 -1
  68. data/spec/unit/core/yum_spec.rb +1 -1
  69. data/spec/unit/mode_spec.rb +2 -2
  70. data/spec/unit/remote/cluster_spec.rb +3 -1
  71. data/spec/unit/remote/cpu_spec.rb +1 -2
  72. data/spec/unit/remote/env_spec.rb +1 -3
  73. data/spec/unit/util_spec.rb +13 -0
  74. metadata +23 -4
@@ -84,6 +84,13 @@ module Kanrisuru
84
84
  append_value("| #{value}")
85
85
  end
86
86
 
87
+ def append_array(value)
88
+ return unless Kanrisuru::Util.present?(value)
89
+
90
+ value = [value] if value.instance_of?(String)
91
+ append_value(value.join(' '))
92
+ end
93
+
87
94
  def append_value(value)
88
95
  @raw_command = "#{@raw_command} #{value}"
89
96
  end
@@ -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'
@@ -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,46 +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_options = exclude.instance_of?(String) ? [exclude] : exclude
74
- exclude_options.each do |exclude_option|
75
- command << "--exclude=#{exclude_option}"
68
+ options = exclude.instance_of?(String) ? [exclude] : exclude
69
+ options.each do |option|
70
+ command << "--exclude=#{option}"
76
71
  end
77
72
  end
78
73
 
79
- if Kanrisuru::Util.present?(paths)
80
- paths = paths.instance_of?(String) ? [paths] : paths
81
- command << paths.join(' ')
82
- end
74
+ command.append_array(paths)
83
75
 
84
76
  execute_shell(command)
85
77
  Kanrisuru::Result.new(command)
86
78
  when 'append', 'r'
87
79
  command.append_flag('-r')
88
-
89
- if Kanrisuru::Util.present?(paths)
90
- paths = paths.instance_of?(String) ? [paths] : paths
91
- command << paths.join(' ')
92
- end
80
+ command.append_array(paths)
93
81
 
94
82
  execute_shell(command)
95
83
  Kanrisuru::Result.new(command)
96
84
  when 'catenate', 'concat', 'A'
97
85
  command.append_flag('-A')
98
-
99
- if Kanrisuru::Util.present?(paths)
100
- paths = paths.instance_of?(String) ? [paths] : paths
101
- command << paths.join(' ')
102
- end
86
+ command.append_array(paths)
103
87
 
104
88
  execute_shell(command)
105
89
  Kanrisuru::Result.new(command)
106
90
  when 'update', 'u'
107
91
  command.append_flag('-u')
108
-
109
- if Kanrisuru::Util.present?(paths)
110
- paths = paths.instance_of?(String) ? [paths] : paths
111
- command << paths.join(' ')
112
- end
92
+ command.append_array(paths)
113
93
 
114
94
  execute_shell(command)
115
95
  Kanrisuru::Result.new(command)
@@ -122,11 +102,7 @@ module Kanrisuru
122
102
  when 'delete'
123
103
  command.append_flag('--delete')
124
104
  command.append_arg('--occurrence', opts[:occurrence])
125
-
126
- if Kanrisuru::Util.present?(paths)
127
- paths = paths.instance_of?(String) ? [paths] : paths
128
- command << paths.join(' ')
129
- end
105
+ command.append_array(paths)
130
106
 
131
107
  execute_shell(command)
132
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