kamaze-docker_image 0.0.5

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 (31) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +6 -0
  3. data/.yardopts +16 -0
  4. data/lib/kamaze-docker_image.rb +24 -0
  5. data/lib/kamaze/docker_image.rb +223 -0
  6. data/lib/kamaze/docker_image/command.rb +79 -0
  7. data/lib/kamaze/docker_image/concern.rb +22 -0
  8. data/lib/kamaze/docker_image/concern/containers.rb +75 -0
  9. data/lib/kamaze/docker_image/concern/docker.rb +36 -0
  10. data/lib/kamaze/docker_image/concern/executable.rb +24 -0
  11. data/lib/kamaze/docker_image/concern/readable_attrs.rb +48 -0
  12. data/lib/kamaze/docker_image/concern/setup.rb +98 -0
  13. data/lib/kamaze/docker_image/concern/setup/config.rb +35 -0
  14. data/lib/kamaze/docker_image/loader.rb +61 -0
  15. data/lib/kamaze/docker_image/loader/context.rb +57 -0
  16. data/lib/kamaze/docker_image/loader/helper.rb +99 -0
  17. data/lib/kamaze/docker_image/loader/tasks.rb +22 -0
  18. data/lib/kamaze/docker_image/loader/tasks/build.rb +23 -0
  19. data/lib/kamaze/docker_image/loader/tasks/exec.rb +19 -0
  20. data/lib/kamaze/docker_image/loader/tasks/push.rb +19 -0
  21. data/lib/kamaze/docker_image/loader/tasks/restart.rb +21 -0
  22. data/lib/kamaze/docker_image/loader/tasks/run.rb +19 -0
  23. data/lib/kamaze/docker_image/loader/tasks/ssh.rb +19 -0
  24. data/lib/kamaze/docker_image/loader/tasks/start.rb +19 -0
  25. data/lib/kamaze/docker_image/loader/tasks/stop.rb +19 -0
  26. data/lib/kamaze/docker_image/runner.rb +126 -0
  27. data/lib/kamaze/docker_image/runner/storage.rb +78 -0
  28. data/lib/kamaze/docker_image/ssh.rb +143 -0
  29. data/lib/kamaze/docker_image/version.rb +13 -0
  30. data/lib/kamaze/docker_image/version.yml +17 -0
  31. metadata +99 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: fad5772cb626cf0f9a7be4b64b3c5f32dd14daff83f8eccc6345e22d5120b8aa
4
+ data.tar.gz: ae5b2cfd9b17dba7827f5e7d88763c6bee9e24dc55b6f567661fb147b0e1f89d
5
+ SHA512:
6
+ metadata.gz: 073c70b2161a1d37569e3fe44ff94447a8219f31bae85518d97e59a9c098569c9d75739c3d3c427c6cf506d51a1125cb5e3230669071e874a565955be0e87893
7
+ data.tar.gz: 7f2c5d696672fdb98f8d696ebb5185ed1b0df1bd695b99277bfc27922635b3da522ec29aeefdde1d7798f0c49828220f63cf70bd73e2af7166f9ab668a1232b4
data/.rubocop.yml ADDED
@@ -0,0 +1,6 @@
1
+ ---
2
+ inherit_gem:
3
+ kamaze-project:
4
+ - .rubocop.yml
5
+ AllCops:
6
+ NewCops: disable
data/.yardopts ADDED
@@ -0,0 +1,16 @@
1
+ # vim: ft=sh
2
+
3
+ lib/**/*.rb \
4
+ --no-progress \
5
+ --markup-provider 'redcarpet' \
6
+ --markup 'markdown' \
7
+ --charset 'utf-8' \
8
+ --protected --private --embed-mixins \
9
+ --tag type:'type' --hide-tag 'type' \
10
+ --readme README.md \
11
+ --exclude '_flymake\\.rb$' \
12
+ --exclude '/\\.#'
13
+
14
+ # Local Variables:
15
+ # mode: sh
16
+ # End:
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (C) 2017-2021 Dimitri Arrigoni <dimitri@arrigoni.me>
4
+ # License GPLv3+: GNU GPL version 3 or later
5
+ # <http://www.gnu.org/licenses/gpl.html>.
6
+ # This is free software: you are free to change and redistribute it.
7
+ # There is NO WARRANTY, to the extent permitted by law.
8
+
9
+ $LOAD_PATH.unshift(__dir__)
10
+
11
+ lock = Dir.chdir("#{__dir__}/..") do
12
+ [['gems.rb', 'gems.locked'], ['Gemfile', 'Gemfile.lock']]
13
+ .map { |m| Dir.glob(m).size >= 2 }
14
+ .include?(true)
15
+ end
16
+
17
+ if lock
18
+ require 'rubygems'
19
+ require 'bundler/setup'
20
+
21
+ if Gem::Specification.find_all_by_name('kamaze-project').any?
22
+ require 'kamaze/project/core_ext/pp'
23
+ end
24
+ end
@@ -0,0 +1,223 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (C) 2017-2021 Dimitri Arrigoni <dimitri@arrigoni.me>
4
+ # License GPLv3+: GNU GPL version 3 or later
5
+ # <http://www.gnu.org/licenses/gpl.html>.
6
+ # This is free software: you are free to change and redistribute it.
7
+ # There is NO WARRANTY, to the extent permitted by law.
8
+
9
+ # rubocop:disable Style/Documentation
10
+
11
+ module Kamaze
12
+ end
13
+
14
+ # rubocop:enable Style/Documentation
15
+
16
+ # Describe a docker image
17
+ class Kamaze::DockerImage
18
+ # Get commands
19
+ #
20
+ # Commands as run by runner
21
+ #
22
+ # @see Kamaze::DockerImage::Runner#command
23
+ # @see Kamaze::DockerImage::Concern::Setup#default_commands
24
+ #
25
+ # @return [Hash]
26
+ attr_reader :commands
27
+
28
+ # Get image name
29
+ #
30
+ # @return [String]
31
+ attr_reader :name
32
+
33
+ # Get version
34
+ #
35
+ # @return [String]
36
+ attr_reader :version
37
+
38
+ # Get namespace used for tasks
39
+ #
40
+ # @return [String|Symbol|nil]
41
+ attr_reader :tasks_ns
42
+
43
+ # Get name used to run container
44
+ #
45
+ # @return [String]
46
+ attr_reader :run_as
47
+
48
+ # Config related to ssh.
49
+ #
50
+ # @return [Hash|nil]
51
+ attr_reader :ssh
52
+
53
+ # Executable path or name for ``docker``
54
+ #
55
+ # @return [String]
56
+ attr_reader :docker_bin
57
+
58
+ attr_reader :tasks_load
59
+
60
+ # Get default command for ``exec``
61
+ #
62
+ # @see Runner#exec
63
+ #
64
+ # @return [String]
65
+ attr_reader :exec_command
66
+
67
+ autoload(:Pathname, 'pathname')
68
+ autoload(:Open3, 'open3')
69
+ autoload(:JSON, 'json')
70
+
71
+ {
72
+ Concern: 'concern',
73
+ Command: 'command',
74
+ Runner: 'runner',
75
+ SSH: 'ssh',
76
+ Loader: 'loader',
77
+ VERSION: 'version',
78
+ }.each { |k, v| autoload(k, "#{__dir__}/docker_image/#{v}") }
79
+
80
+ include Concern::Executable
81
+ include Concern::Setup
82
+ include Concern::ReadableAttrs
83
+
84
+ def initialize(&block)
85
+ setup(caller_locations, &block)
86
+
87
+ @runner = Runner.new(self)
88
+ @ssh = SSH.new(self).freeze
89
+ tasks_load! if tasks_load?
90
+ end
91
+
92
+ # Get image id (through docker command).
93
+ #
94
+ # @return [String, nil]
95
+ def id
96
+ # docker image list --format "{{json .ID}}" image_name:image_version
97
+ [
98
+ self.to_h[:docker_bin] || executable
99
+ ].concat(['image', 'list', '--format', '{{json .ID}}', self.to_s]).yield_self do |command|
100
+ Open3.capture3(*command).tap do |stdout, _, status|
101
+ return nil unless status.success?
102
+
103
+ return stdout.lines.empty? ? nil : JSON.parse(stdout.lines.first)
104
+ end
105
+ end
106
+ end
107
+
108
+ # Denote image is started.
109
+ #
110
+ # @return [Boolean]
111
+ def started?
112
+ runner.started?
113
+ end
114
+
115
+ # Denote image is running?.
116
+ #
117
+ # @return [Boolean]
118
+ def running?
119
+ runner.running?
120
+ end
121
+
122
+ # Get name of available commands.
123
+ #
124
+ # @return [Array<Symbol>]
125
+ def available_commands
126
+ commands.clone.reject { |_k, args| args.nil? }.to_h.keys.sort
127
+ end
128
+
129
+ # Get tag
130
+ #
131
+ # tag has the following format: ``#{name}:#{version}``
132
+ #
133
+ # @return [String]
134
+ def tag
135
+ "#{name}:#{version}"
136
+ end
137
+
138
+ alias to_s tag
139
+
140
+ # @return [Hash]
141
+ def to_h
142
+ readable_attrs_values
143
+ .to_h.tap { |h| h.merge!(tag: tag) }
144
+ .sort.to_h
145
+ end
146
+
147
+ # @return [Boolean]
148
+ def verbose?
149
+ !!@verbose
150
+ end
151
+
152
+ # @return [Boolean]
153
+ def tasks_load?
154
+ !!self.tasks_load
155
+ end
156
+
157
+ # @return [Pathname]
158
+ def path
159
+ Pathname.new(@path)
160
+ end
161
+
162
+ # @see Runner#actions
163
+ def method_missing(method, *args, &block)
164
+ respond_to_missing?(method) ? runner.public_send(method, *args, &block) : super
165
+ end
166
+
167
+ def respond_to_missing?(method, include_private = false)
168
+ # rubocop:disable Style/RedundantParentheses
169
+ (runner&.actions).to_a.include?(method.to_sym) || super(method, include_private)
170
+ # rubocop:enable Style/RedundantParentheses
171
+ end
172
+
173
+ protected
174
+
175
+ # @type [String]
176
+ attr_writer :name
177
+
178
+ # @see Concern::Setup#setup_defaults
179
+ # @type [String]
180
+ attr_writer :path
181
+
182
+ # @see Concern::Setup#setup_defaults
183
+ # @type [Boolean]
184
+ attr_writer :verbose
185
+
186
+ # @see Concern::Setup#setup_defaults
187
+ # @type [String]
188
+ attr_writer :version
189
+
190
+ # @type [String|nil]
191
+ attr_writer :tasks_ns
192
+
193
+ # @see Concern::Setup#setup_defaults
194
+ # @type [String]
195
+ attr_writer :tasks_load
196
+
197
+ # @see Concern::Setup#setup_defaults
198
+ # @type [String]
199
+ attr_writer :run_as
200
+
201
+ # @see Concern::Setup#setup_defaults
202
+ # @type [String]
203
+ attr_writer :exec_command
204
+
205
+ # @type [Hash]
206
+ attr_writer :ssh
207
+
208
+ # @see Concern::Setup#setup_defaults
209
+ # @type [Hash]
210
+ attr_writer :commands
211
+
212
+ # @see Concern::Setup#setup_defaults
213
+ # @type [String|Symbol]
214
+ attr_writer :docker_bin
215
+
216
+ # @return [Runner]
217
+ attr_reader :runner
218
+
219
+ # Load tasks
220
+ def tasks_load!
221
+ self.tap { Loader.new(self).call }
222
+ end
223
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (C) 2017-2021 Dimitri Arrigoni <dimitri@arrigoni.me>
4
+ # License GPLv3+: GNU GPL version 3 or later
5
+ # <http://www.gnu.org/licenses/gpl.html>.
6
+ # This is free software: you are free to change and redistribute it.
7
+ # There is NO WARRANTY, to the extent permitted by law.
8
+
9
+ require_relative '../docker_image'
10
+
11
+ # Describe a command
12
+ #
13
+ # Command is able to run itself.
14
+ class Kamaze::DockerImage::Command
15
+ autoload :Shellwords, 'shellwords'
16
+
17
+ # @return [Hash]
18
+ attr_reader :config
19
+
20
+ # @param [Array<String>] command
21
+ # @param [Hash] config
22
+ # @param [String|nil] extra
23
+ def initialize(command, config = {}, extra = nil)
24
+ command.clone.to_a.tap do |c|
25
+ extras = Shellwords.split(extra.to_s).compact
26
+ @parts = c.push(*extras).freeze
27
+ end
28
+
29
+ config.clone.to_h.tap do |c|
30
+ @config = c.freeze
31
+ end
32
+ end
33
+
34
+ # @return [Array<String>]
35
+ def to_a
36
+ parts.clone
37
+ end
38
+
39
+ # @return [String]
40
+ def to_s
41
+ Shellwords.join(self.to_a)
42
+ end
43
+
44
+ def run(&block)
45
+ sh(*self.to_a, &block)
46
+ end
47
+
48
+ alias call run
49
+
50
+ # @return [Boolean]
51
+ def execute
52
+ system(*self.to_a)
53
+ end
54
+
55
+ protected
56
+
57
+ # @return [Array<String>]
58
+ attr_reader :parts
59
+
60
+ # Get utils.
61
+ #
62
+ # return [Class]
63
+ def utils
64
+ if Gem::Specification.find_all_by_name('rake')
65
+ require 'rake'
66
+ require 'rake/file_utils'
67
+ end
68
+
69
+ Class.new { include FileUtils }.new
70
+ end
71
+
72
+ # @see https://github.com/ruby/rake/blob/124a03bf4c0db41cd80a41394a9e7c6426e44784/lib/rake/file_utils.rb#L43
73
+ def sh(*cmd, &block)
74
+ options = cmd.last.is_a?(Hash) ? cmd.pop : {}
75
+ options[:verbose] = config[:verbose] unless options.key?(:verbose)
76
+
77
+ utils.sh(*cmd.map(&:to_s).push(options), &block)
78
+ end
79
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (C) 2017-2021 Dimitri Arrigoni <dimitri@arrigoni.me>
4
+ # License GPLv3+: GNU GPL version 3 or later
5
+ # <http://www.gnu.org/licenses/gpl.html>.
6
+ # This is free software: you are free to change and redistribute it.
7
+ # There is NO WARRANTY, to the extent permitted by law.
8
+
9
+ require_relative '../docker_image'
10
+
11
+ # rubocop:disable Style/Documentation
12
+
13
+ module Kamaze::DockerImage::Concern
14
+ {
15
+ Containers: 'containers',
16
+ Setup: 'setup',
17
+ Executable: 'executable',
18
+ ReadableAttrs: 'readable_attrs',
19
+ }.each { |k, v| autoload(k, "#{__dir__}/concern/#{v}") }
20
+ end
21
+
22
+ # rubocop:enable Style/Documentation
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (C) 2017-2021 Dimitri Arrigoni <dimitri@arrigoni.me>
4
+ # License GPLv3+: GNU GPL version 3 or later
5
+ # <http://www.gnu.org/licenses/gpl.html>.
6
+ # This is free software: you are free to change and redistribute it.
7
+ # There is NO WARRANTY, to the extent permitted by law.
8
+
9
+ require_relative '../concern'
10
+
11
+ # Provide containers method.
12
+ module Kamaze::DockerImage::Concern::Containers
13
+ include Kamaze::DockerImage::Concern::Executable
14
+
15
+ autoload(:Open3, 'open3')
16
+ autoload(:JSON, 'json')
17
+
18
+ protected
19
+
20
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
21
+
22
+ # List containers.
23
+ #
24
+ # Containers are indexed by name.
25
+ #
26
+ # @return [Hash{String => Hash}]
27
+ def containers(all: true)
28
+ [(config[:docker_bin] || executable).to_s].map(&:freeze).freeze.yield_self do |cmd|
29
+ cmd.dup.concat(['ps', (all ? '-a' : nil), '--format', '{{json .}}']).yield_self do |command|
30
+ [].tap do |items|
31
+ Open3.capture3(*command.compact).yield_self do |stdout, _, status|
32
+ stdout.lines.each { |line| items.push(JSON.parse(line)) } if status.success?
33
+ end
34
+ end
35
+ end.map { |h| containers_maker.call(h) }.map { |h| [h.info['Name'].gsub(%r{^/*}, '').to_s, h] }.to_h
36
+ end
37
+ end
38
+
39
+ # Add some methods on retrieved info.
40
+ #
41
+ # @api private
42
+ #
43
+ # @return [Proc}
44
+ def containers_maker
45
+ # @type [Hash{String => Object}] given_data
46
+ lambda do |given_data|
47
+ command = [(config[:docker_bin] || executable).to_s]
48
+ .map(&:freeze)
49
+ .concat(['inspect', '--format', '{{json .}}', given_data.fetch('ID')])
50
+
51
+ given_data.dup.tap do |result|
52
+ result.singleton_class.tap do |klass|
53
+ :inspection.tap do |method_name|
54
+ klass.__send__(:define_method, method_name) do
55
+ -> { Struct.new(:stdout, :stderr, :status).new(*Open3.capture3(*command.compact)) }
56
+ end
57
+ klass.__send__(:protected, method_name)
58
+ end
59
+
60
+ klass.__send__(:define_method, :info) do
61
+ inspection.call.yield_self do |v|
62
+ (v.status.success? ? JSON.parse(v.stdout) : nil).to_h
63
+ end
64
+ end
65
+
66
+ klass.__send__(:define_method, :running?) do
67
+ self.info['State'].to_h['Status'] == 'running'
68
+ end
69
+ end
70
+ end.freeze
71
+ end
72
+ end
73
+
74
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
75
+ end