kanrisuru 0.1.0 → 0.2.1

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