kanrisuru 0.1.0 → 0.2.1

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 (81) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +17 -0
  3. data/.rubocop.yml +47 -0
  4. data/.rubocop_todo.yml +0 -0
  5. data/CHANGELOG.md +0 -0
  6. data/Gemfile +2 -5
  7. data/LICENSE.txt +1 -1
  8. data/README.md +143 -7
  9. data/Rakefile +5 -3
  10. data/bin/console +4 -3
  11. data/kanrisuru.gemspec +21 -12
  12. data/lib/kanrisuru.rb +41 -2
  13. data/lib/kanrisuru/command.rb +99 -0
  14. data/lib/kanrisuru/core.rb +53 -0
  15. data/lib/kanrisuru/core/archive.rb +154 -0
  16. data/lib/kanrisuru/core/disk.rb +302 -0
  17. data/lib/kanrisuru/core/file.rb +332 -0
  18. data/lib/kanrisuru/core/find.rb +108 -0
  19. data/lib/kanrisuru/core/group.rb +97 -0
  20. data/lib/kanrisuru/core/ip.rb +1032 -0
  21. data/lib/kanrisuru/core/mount.rb +138 -0
  22. data/lib/kanrisuru/core/path.rb +140 -0
  23. data/lib/kanrisuru/core/socket.rb +168 -0
  24. data/lib/kanrisuru/core/stat.rb +104 -0
  25. data/lib/kanrisuru/core/stream.rb +121 -0
  26. data/lib/kanrisuru/core/system.rb +348 -0
  27. data/lib/kanrisuru/core/transfer.rb +203 -0
  28. data/lib/kanrisuru/core/user.rb +198 -0
  29. data/lib/kanrisuru/logger.rb +8 -0
  30. data/lib/kanrisuru/mode.rb +277 -0
  31. data/lib/kanrisuru/os_package.rb +235 -0
  32. data/lib/kanrisuru/remote.rb +10 -0
  33. data/lib/kanrisuru/remote/cluster.rb +95 -0
  34. data/lib/kanrisuru/remote/cpu.rb +68 -0
  35. data/lib/kanrisuru/remote/env.rb +33 -0
  36. data/lib/kanrisuru/remote/file.rb +354 -0
  37. data/lib/kanrisuru/remote/fstab.rb +412 -0
  38. data/lib/kanrisuru/remote/host.rb +191 -0
  39. data/lib/kanrisuru/remote/memory.rb +19 -0
  40. data/lib/kanrisuru/remote/os.rb +87 -0
  41. data/lib/kanrisuru/result.rb +78 -0
  42. data/lib/kanrisuru/template.rb +32 -0
  43. data/lib/kanrisuru/util.rb +40 -0
  44. data/lib/kanrisuru/util/bits.rb +203 -0
  45. data/lib/kanrisuru/util/fs_mount_opts.rb +655 -0
  46. data/lib/kanrisuru/util/os_family.rb +213 -0
  47. data/lib/kanrisuru/util/signal.rb +161 -0
  48. data/lib/kanrisuru/version.rb +3 -1
  49. data/spec/functional/core/archive_spec.rb +228 -0
  50. data/spec/functional/core/disk_spec.rb +80 -0
  51. data/spec/functional/core/file_spec.rb +341 -0
  52. data/spec/functional/core/find_spec.rb +52 -0
  53. data/spec/functional/core/group_spec.rb +65 -0
  54. data/spec/functional/core/ip_spec.rb +71 -0
  55. data/spec/functional/core/path_spec.rb +93 -0
  56. data/spec/functional/core/socket_spec.rb +31 -0
  57. data/spec/functional/core/stat_spec.rb +98 -0
  58. data/spec/functional/core/stream_spec.rb +99 -0
  59. data/spec/functional/core/system_spec.rb +96 -0
  60. data/spec/functional/core/transfer_spec.rb +108 -0
  61. data/spec/functional/core/user_spec.rb +76 -0
  62. data/spec/functional/os_package_spec.rb +75 -0
  63. data/spec/functional/remote/cluster_spec.rb +45 -0
  64. data/spec/functional/remote/cpu_spec.rb +41 -0
  65. data/spec/functional/remote/env_spec.rb +36 -0
  66. data/spec/functional/remote/fstab_spec.rb +76 -0
  67. data/spec/functional/remote/host_spec.rb +68 -0
  68. data/spec/functional/remote/memory_spec.rb +29 -0
  69. data/spec/functional/remote/os_spec.rb +63 -0
  70. data/spec/functional/remote/remote_file_spec.rb +180 -0
  71. data/spec/helper/test_hosts.rb +68 -0
  72. data/spec/hosts.json +92 -0
  73. data/spec/spec_helper.rb +11 -3
  74. data/spec/unit/fstab_spec.rb +22 -0
  75. data/spec/unit/kanrisuru_spec.rb +9 -0
  76. data/spec/unit/mode_spec.rb +183 -0
  77. data/spec/unit/template_spec.rb +13 -0
  78. data/spec/unit/util_spec.rb +177 -0
  79. data/spec/zz_reboot_spec.rb +46 -0
  80. metadata +136 -13
  81. data/spec/kanrisuru_spec.rb +0 -9
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kanrisuru
4
+ module Remote
5
+ class Memory
6
+ def initialize(host)
7
+ @host = host
8
+ end
9
+
10
+ method_names = %w[total free swap swap_free]
11
+ method_names.each do |method_name|
12
+ define_method(method_name.to_s) do |metric = :kb|
13
+ value = @host.free(method_name).to_i
14
+ metric == :kb ? value : Kanrisuru::Util::Bits.convert_from_kb(value, metric)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kanrisuru
4
+ module Remote
5
+ class Os
6
+ attr_reader :processor, :operating_system, :release, :version
7
+
8
+ def initialize(host)
9
+ Kanrisuru.logger.info('Gathering OS details')
10
+
11
+ @host = host
12
+ @kernel_name = uname(kernel_name: true)
13
+
14
+ case @kernel_name
15
+ when 'Linux'
16
+ initialize_linux
17
+ end
18
+ end
19
+
20
+ def kernel
21
+ @kernel_name
22
+ end
23
+
24
+ def linux?
25
+ kernel == 'Linux'
26
+ end
27
+
28
+ def uname(opts = {})
29
+ command = Kanrisuru::Command.new('uname')
30
+
31
+ if opts[:all]
32
+ command.append_flag('-a', opts[:all])
33
+ else
34
+ command.append_flag('-s', opts[:kernel_name])
35
+ command.append_flag('-n', opts[:node_name])
36
+ command.append_flag('-r', opts[:kernel_release])
37
+ command.append_flag('-v', opts[:kernel_version])
38
+ command.append_flag('-m', opts[:machine])
39
+ command.append_flag('-p', opts[:processor])
40
+ command.append_flag('-i', opts[:hardware_platform])
41
+ command.append_flag('-o', opts[:operating_system])
42
+ end
43
+
44
+ @host.execute(command)
45
+
46
+ return unless command.success?
47
+
48
+ if opts.keys.length > 1 || opts[:all]
49
+ command.to_a
50
+ else
51
+ command.to_s
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def initialize_linux
58
+ @kernel_version = uname(kernel_version: true)
59
+ machine = uname(machine: true)
60
+ processor = uname(processor: true)
61
+ @operating_system = uname(operating_system: true)
62
+ @hardware_platform = uname(hardware_platform: true)
63
+
64
+ @processor = processor == 'unknown' ? machine : processor
65
+
66
+ @release = parse_os_release
67
+ @version = parse_os_version
68
+ end
69
+
70
+ def parse_os_release
71
+ command = Kanrisuru::Command.new("cat /etc/os-release | grep '^ID=' | awk -F= '{ print $2}'")
72
+ result = @host.execute(command)
73
+ raise 'Invalid os release' if result.failure?
74
+
75
+ result.to_s.gsub(/"/, '')
76
+ end
77
+
78
+ def parse_os_version
79
+ command = Kanrisuru::Command.new("cat /etc/os-release | grep '^VERSION_ID=' | awk -F= '{ print $2}'")
80
+ result = @host.execute(command)
81
+ raise 'Invalid os version' if result.failure?
82
+
83
+ result.to_s.gsub(/"/, '').to_f
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kanrisuru
4
+ class Result
5
+ include Enumerable
6
+
7
+ attr_reader :error, :data, :command
8
+
9
+ def initialize(command, &block)
10
+ @command = command
11
+ @data = nil
12
+
13
+ @data = block.call(@command) if @command.success? && block_given?
14
+ @error = @command.to_a if @command.failure?
15
+
16
+ ## Define getter methods on result that maps to
17
+ ## the same methods of a data struct.
18
+ return unless @command.success? && Kanrisuru::Util.present?(@data) && @data.class.ancestors.include?(Struct)
19
+
20
+ method_names = @data.members
21
+ self.class.class_eval do
22
+ method_names.each do |method_name|
23
+ define_method method_name do
24
+ @data[method_name]
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ def [](prop)
31
+ @data[prop]
32
+ end
33
+
34
+ def to_a
35
+ @data.instance_of?(Array) ? @data : [@data]
36
+ end
37
+
38
+ def to_i
39
+ if @data.instance_of?(Integer)
40
+ @data
41
+ elsif @data.instance_of?(String)
42
+ @data.to_i
43
+ elsif @data.instance_of?(Array)
44
+ @data.map(&:to_i)
45
+ elsif @data.instance_of?(NilClass)
46
+ nil
47
+ else
48
+ raise NoMethodError, "(undefined method `to_i' for Kanrisuru::Result)"
49
+ end
50
+ end
51
+
52
+ def inspect
53
+ if success?
54
+ format('#<Kanrisuru::Result:0x%<object_id>s @status=%<status>s @data=%<data>s @command=%<command>s>',
55
+ object_id: object_id, status: status, data: @data.inspect, command: command.prepared_command)
56
+ else
57
+ format('#<Kanrisuru::Result:0x%<object_id>s @status=%<status>s @error=%<error>s @command=%<command>s>',
58
+ object_id: object_id, status: status, error: @error.inspect, command: command.prepared_command)
59
+ end
60
+ end
61
+
62
+ def failure?
63
+ @command.failure?
64
+ end
65
+
66
+ def success?
67
+ @command.success?
68
+ end
69
+
70
+ def status
71
+ @command.exit_status
72
+ end
73
+
74
+ def each(&block)
75
+ @data.each { |item| block.call(item) } if @data.instance_of?(Array)
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'erb'
4
+
5
+ module Kanrisuru
6
+ class Template
7
+ attr_writer :trim_mode
8
+
9
+ def initialize(path, args = {})
10
+ @path = path
11
+ @trim_mode = '-'
12
+
13
+ args.each do |variable_name, value|
14
+ instance_variable_set("@#{variable_name}", value)
15
+ end
16
+ end
17
+
18
+ def render
19
+ erb.result(binding)
20
+ end
21
+
22
+ def read
23
+ StringIO.new(render)
24
+ end
25
+
26
+ private
27
+
28
+ def erb
29
+ ERB.new(File.read(@path), trim_mode: @trim_mode)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'util/bits'
4
+ require_relative 'util/os_family'
5
+ require_relative 'util/fs_mount_opts'
6
+ require_relative 'util/signal'
7
+
8
+ module Kanrisuru
9
+ class Util
10
+ def self.blank?(value)
11
+ value.respond_to?(:empty?) ? value.empty? : !value
12
+ end
13
+
14
+ def self.present?(value)
15
+ !Kanrisuru::Util.blank?(value)
16
+ end
17
+
18
+ def self.array_join_string(arg)
19
+ arg.instance_of?(Array) ? arg.join(',') : arg
20
+ end
21
+
22
+ def self.string_join_array(arg)
23
+ array = arg.instance_of?(String) ? [arg] : arg
24
+ array.join(',')
25
+ end
26
+
27
+ def self.numeric?(value)
28
+ !Float(value).nil?
29
+ rescue StandardError
30
+ false
31
+ end
32
+
33
+ def self.camelize(string)
34
+ string = string.to_s
35
+ string = string.sub(/^[a-z\d]*/, &:capitalize)
36
+ string.gsub!(%r{(?:_|(/))([a-z\d]*)}i) { "#{Regexp.last_match(1)}#{Regexp.last_match(2).capitalize}" }
37
+ string
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,203 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kanrisuru
4
+ class Util
5
+ class Bits
6
+ def self.convert_from_kb(value, metric)
7
+ convert_bytes(value, :kilobyte, metric)
8
+ end
9
+
10
+ def self.convert_from_mb(value, metric)
11
+ convert_bytes(value, :megabyte, metric)
12
+ end
13
+
14
+ def self.convert_from_gb(value, metric)
15
+ convert_bytes(value, :gigabyte, metric)
16
+ end
17
+
18
+ def self.convert_from_tb(value, metric)
19
+ convert_bytes(value, :terabyte, metric)
20
+ end
21
+
22
+ def self.convert_from_pb(value, metric)
23
+ convert_bytes(value, :petabyte, metric)
24
+ end
25
+
26
+ def self.convert_bytes(value, from, to)
27
+ from = from.downcase.to_sym
28
+ to = to.downcase.to_sym
29
+
30
+ byte_translations = {
31
+ b: :deca,
32
+ kb: :kilo,
33
+ mb: :mega,
34
+ gb: :giga,
35
+ tb: :tera,
36
+ pb: :peta,
37
+ byte: :deca,
38
+ kilobyte: :kilo,
39
+ megabyte: :mega,
40
+ gigabyte: :giga,
41
+ terabyte: :tera,
42
+ petabyte: :peta
43
+ }
44
+
45
+ bit_translations = {
46
+ kib: :kilo,
47
+ mib: :mega,
48
+ gib: :giga,
49
+ tib: :tera,
50
+ pib: :peta,
51
+ bit: :deca,
52
+ kilobit: :kilo,
53
+ megabit: :mega,
54
+ gigabit: :giga,
55
+ terabit: :tera,
56
+ petabit: :peta
57
+ }
58
+
59
+ bit_translation_from = false
60
+ bit_translation_to = false
61
+
62
+ from =
63
+ if bit_translations.key?(from)
64
+ bit_translation_from = true
65
+ bit_translations[from]
66
+ elsif byte_translations.key?(from)
67
+ byte_translations[from]
68
+ else
69
+ raise ArgumentError, 'Invalid data type'
70
+ end
71
+
72
+ to =
73
+ if bit_translations.key?(to)
74
+ bit_translation_to = true
75
+ bit_translations[to]
76
+ elsif byte_translations.key?(to)
77
+ byte_translations[to]
78
+ else
79
+ raise ArgumentError, 'Invalid data type'
80
+ end
81
+
82
+ multiplier = if bit_translation_from && !bit_translation_to
83
+ (1.to_f / 8).to_f
84
+ elsif !bit_translation_from && bit_translation_to
85
+ 8
86
+ else
87
+ 1
88
+ end
89
+
90
+ power = convert_power(from, to)
91
+
92
+ (value * 1000.pow(power).to_f) * multiplier
93
+ end
94
+
95
+ def self.convert_power(from_metric, to_metric)
96
+ @conversions ||= {
97
+ deca: {
98
+ deca: 0,
99
+ kilo: -1,
100
+ mega: -2,
101
+ giga: -3,
102
+ tera: -4,
103
+ peta: -5,
104
+ exa: -6,
105
+ zetta: -7,
106
+ yotta: -8
107
+ },
108
+ kilo: {
109
+ deca: 1,
110
+ kilo: 0,
111
+ mega: -1,
112
+ giga: -2,
113
+ tera: -3,
114
+ peta: -4,
115
+ exa: -5,
116
+ zetta: -6,
117
+ yotta: -7
118
+ },
119
+ mega: {
120
+ deca: 2,
121
+ kilo: 1,
122
+ mega: 0,
123
+ giga: -1,
124
+ tera: -2,
125
+ peta: -3,
126
+ exa: -4,
127
+ zetta: -5,
128
+ yotta: -6
129
+ },
130
+ giga: {
131
+ deca: 3,
132
+ kilo: 2,
133
+ mega: 1,
134
+ giga: 0,
135
+ tera: -1,
136
+ peta: -2,
137
+ exa: -3,
138
+ zetta: -4,
139
+ yotta: -5
140
+ },
141
+ tera: {
142
+ deca: 4,
143
+ kilo: 3,
144
+ mega: 2,
145
+ giga: 1,
146
+ tera: 0,
147
+ peta: -1,
148
+ exa: -2,
149
+ zetta: -3,
150
+ yotta: -4
151
+ },
152
+ peta: {
153
+ deca: 5,
154
+ kilo: 4,
155
+ mega: 3,
156
+ giga: 2,
157
+ tera: 1,
158
+ peta: 0,
159
+ exa: -1,
160
+ zetta: -2,
161
+ yotta: -3
162
+ },
163
+ exa: {
164
+ deca: 6,
165
+ kilo: 5,
166
+ mega: 4,
167
+ giga: 3,
168
+ tera: 2,
169
+ peta: 1,
170
+ exa: 0,
171
+ zetta: -1,
172
+ yotta: -2
173
+ },
174
+ zetta: {
175
+ deca: 7,
176
+ kilo: 6,
177
+ mega: 5,
178
+ giga: 4,
179
+ tera: 3,
180
+ peta: 2,
181
+ exa: 1,
182
+ zetta: 0,
183
+ yotta: -1
184
+ },
185
+ yotta: {
186
+ deca: 8,
187
+ kilo: 7,
188
+ mega: 6,
189
+ giga: 5,
190
+ tera: 4,
191
+ peta: 3,
192
+ exa: 2,
193
+ zetta: 1,
194
+ yotta: 0
195
+ }
196
+ }
197
+
198
+ values = @conversions[from_metric]
199
+ values ? values[to_metric] : nil
200
+ end
201
+ end
202
+ end
203
+ end