kuby-core 0.11.14 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -0
- data/Gemfile +2 -2
- data/README.md +2 -1
- data/bin/kuby +2 -0
- data/kuby-core.gemspec +2 -2
- data/lib/kuby/basic_logger.rb +1 -1
- data/lib/kuby/cli_base.rb +9 -4
- data/lib/kuby/commands.rb +16 -69
- data/lib/kuby/docker/alpine.rb +2 -1
- data/lib/kuby/docker/app_image.rb +19 -0
- data/lib/kuby/docker/bundler_phase.rb +9 -3
- data/lib/kuby/docker/cli.rb +4 -12
- data/lib/kuby/docker/docker_uri.rb +18 -7
- data/lib/kuby/docker/errors.rb +1 -19
- data/lib/kuby/docker/image.rb +115 -0
- data/lib/kuby/docker/layer.rb +0 -7
- data/lib/kuby/docker/local_tags.rb +9 -10
- data/lib/kuby/docker/package_phase.rb +0 -5
- data/lib/kuby/docker/packages.rb +1 -0
- data/lib/kuby/docker/remote_tags.rb +10 -5
- data/lib/kuby/docker/setup_phase.rb +17 -9
- data/lib/kuby/docker/spec.rb +29 -62
- data/lib/kuby/docker/timestamp_tag.rb +8 -1
- data/lib/kuby/docker/timestamped_image.rb +113 -0
- data/lib/kuby/docker/yarn_phase.rb +2 -2
- data/lib/kuby/docker.rb +27 -25
- data/lib/kuby/environment.rb +1 -10
- data/lib/kuby/kubernetes/bare_metal_provider.rb +53 -0
- data/lib/kuby/kubernetes/deployer.rb +2 -1
- data/lib/kuby/kubernetes/docker_desktop_provider.rb +0 -15
- data/lib/kuby/kubernetes/spec.rb +21 -17
- data/lib/kuby/kubernetes.rb +1 -0
- data/lib/kuby/plugin.rb +2 -2
- data/lib/kuby/plugins/rails_app/assets.rb +60 -70
- data/lib/kuby/plugins/rails_app/assets_image.rb +55 -0
- data/lib/kuby/plugins/rails_app/plugin.rb +54 -213
- data/lib/kuby/plugins/rails_app.rb +1 -0
- data/lib/kuby/tasks.rb +30 -69
- data/lib/kuby/version.rb +1 -1
- data/lib/kuby.rb +3 -20
- data/spec/docker/spec_spec.rb +21 -118
- data/spec/docker/timestamped_image_spec.rb +123 -0
- data/spec/spec_helper.rb +10 -11
- metadata +11 -14
- data/lib/kuby/dev_setup.rb +0 -346
- data/lib/kuby/docker/dev_spec.rb +0 -202
- data/lib/kuby/docker/metadata.rb +0 -90
- data/lib/kuby/docker/tags.rb +0 -92
- data/lib/kuby/rails_commands.rb +0 -84
- data/spec/docker/metadata_spec.rb +0 -73
- data/spec/dummy/Gemfile.lock +0 -223
- data/spec/dummy/config/master.key +0 -1
- data/spec/dummy/tmp/cache/bootsnap-load-path-cache +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a443b66d4dff19f6a2112b6365a9579b0490b049ef51ab612ad9e6cf4a807901
|
4
|
+
data.tar.gz: 2b38151be094c758a64ecdc95c585f184f4e9eea1affbdc4d071cc7a20d499a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6cf93a88bc24ab142fa497daddc7227d417c138391f46db6f5b77a862c96e9c2733d880eded21d464170963902364ac0f2806f84cd083d0a5b408231987bcf2b
|
7
|
+
data.tar.gz: dab2dcd180ff19421ef44aef1a3384e1faa0b49511925e6557d54500a652a5c854217a8c463cd738cd6a745b2eb1804262e35539635fdb4d98ed13d2abc90aa2
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,32 @@
|
|
1
|
+
## 0.13.0
|
2
|
+
* Fix handling rails/rake options in remote exec (@palkan, #60)
|
3
|
+
* Add `bundler_phase.gemfiles(*paths)` to allow adding additional gemfiles (@palkan, #61)
|
4
|
+
|
5
|
+
## 0.12.0
|
6
|
+
* Fix issue causing volume mount errors when k8s tries to schedule asset pods on multiple nodes (fixes #42).
|
7
|
+
- Persistent volumes can only be mounted on a single physical node.
|
8
|
+
- Kuby now creates a separate assets image powered by nginx.
|
9
|
+
- Ingress routes requests to either the Rails service or assets service depending on the URL (i.e. /assets).
|
10
|
+
- Since the ingress layer is now essential, the Docker Desktop provider no longer deletes ingresses or monkeys with service objects. You'll have to either 1) add an entry for your hostname to your hosts file, or 2) set the `Host` header when making requests to your app.
|
11
|
+
* Plugins can now specify additional Dockerfiles to build during `kuby build`.
|
12
|
+
* Switch from TravisCI to Github Actions.
|
13
|
+
* Remove support for development environments.
|
14
|
+
- Proved to be too difficult to maintain.
|
15
|
+
- Kuby is a _deployment_ tool anyway, not a dev tool.
|
16
|
+
- Maybe we can turn the dev stuff into a gem at some point.
|
17
|
+
* Refactor Docker image logic.
|
18
|
+
- Introduced the `Image` class and friends.
|
19
|
+
- Deleted the `Kuby::Docker::Metadata` class.
|
20
|
+
* Add missing git dependency to Alpine distro.
|
21
|
+
* Add a bare metal provider (fixes #10).
|
22
|
+
|
23
|
+
## 0.11.16
|
24
|
+
* Fix yarn phase
|
25
|
+
- Apparently you have to copy at least one file, TIL.
|
26
|
+
|
27
|
+
## 0.11.15
|
28
|
+
* Copy over .npmrc and .yarnrc before running yarn install.
|
29
|
+
|
1
30
|
## 0.11.14
|
2
31
|
* Don't include port in image host for registry secrets (no idea why)
|
3
32
|
|
data/Gemfile
CHANGED
@@ -5,10 +5,10 @@ gemspec
|
|
5
5
|
group :development, :test do
|
6
6
|
gem 'pry-byebug'
|
7
7
|
gem 'rake'
|
8
|
-
|
8
|
+
# lock to a specific version to prevent breaking CI when new versions come out
|
9
|
+
gem 'sorbet', '= 0.5.6433'
|
9
10
|
end
|
10
11
|
|
11
12
|
group :test do
|
12
13
|
gem 'rspec', '~> 3.0'
|
13
|
-
gem 'timecop', '~> 0.9'
|
14
14
|
end
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
## Kuby
|
2
2
|
|
3
|
-
|
3
|
+
![Unit Tests](https://github.com/getkuby/kuby-core/actions/workflows/unit_tests.yml/badge.svg?branch=master)
|
4
|
+
![Integration Tests](https://github.com/getkuby/kuby-core/actions/workflows/integration_tests.yml/badge.svg?branch=master)
|
4
5
|
|
5
6
|
Deploy your Rails app the easy way.
|
6
7
|
|
data/bin/kuby
CHANGED
data/kuby-core.gemspec
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
$:.unshift File.
|
1
|
+
$:.unshift File.expand_path('lib', __dir__)
|
2
2
|
require 'kuby/version'
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.platform = Gem::Platform::RUBY
|
14
14
|
|
15
15
|
s.add_dependency 'colorize', '~> 0.8'
|
16
|
-
s.add_dependency 'docker-remote', '~> 0.
|
16
|
+
s.add_dependency 'docker-remote', '~> 0.6'
|
17
17
|
s.add_dependency 'gli', '~> 2.0'
|
18
18
|
s.add_dependency 'helm-cli', '~> 0.3'
|
19
19
|
# See: https://github.com/Shopify/krane/pull/720
|
data/lib/kuby/basic_logger.rb
CHANGED
data/lib/kuby/cli_base.rb
CHANGED
@@ -7,21 +7,26 @@ module Kuby
|
|
7
7
|
class CLIBase
|
8
8
|
extend T::Sig
|
9
9
|
|
10
|
+
BeforeCallback = T.type_alias { T.proc.params(cmd: T::Array[String]).void }
|
11
|
+
AfterCallback = T.type_alias do
|
12
|
+
T.proc.params(cmd: T::Array[String], last_status: T.nilable(Process::Status)).void
|
13
|
+
end
|
14
|
+
|
10
15
|
sig { returns(T.nilable(Process::Status)) }
|
11
16
|
def last_status
|
12
17
|
Thread.current[status_key]
|
13
18
|
end
|
14
19
|
|
15
|
-
sig { params(block:
|
20
|
+
sig { params(block: BeforeCallback).void }
|
16
21
|
def before_execute(&block)
|
17
|
-
@before_execute = T.let(@before_execute, T.nilable(T::Array[
|
22
|
+
@before_execute = T.let(@before_execute, T.nilable(T::Array[BeforeCallback]))
|
18
23
|
@before_execute ||= []
|
19
24
|
@before_execute << block
|
20
25
|
end
|
21
26
|
|
22
|
-
sig { params(block:
|
27
|
+
sig { params(block: AfterCallback).void }
|
23
28
|
def after_execute(&block)
|
24
|
-
@after_execute = T.let(@after_execute, T.nilable(T::Array[
|
29
|
+
@after_execute = T.let(@after_execute, T.nilable(T::Array[AfterCallback]))
|
25
30
|
@after_execute ||= []
|
26
31
|
@after_execute << block
|
27
32
|
end
|
data/lib/kuby/commands.rb
CHANGED
@@ -25,9 +25,10 @@ module Kuby
|
|
25
25
|
def run(args)
|
26
26
|
if idx = args.index('rails') || idx = args.index('rake')
|
27
27
|
@rails_options = T.let(@rails_options, T.nilable(T::Array[String]))
|
28
|
-
@rails_options = args[idx..-1]
|
28
|
+
@rails_options = args[(idx + 1)..-1]
|
29
29
|
super(args[0..idx])
|
30
30
|
else
|
31
|
+
@rails_options = []
|
31
32
|
super
|
32
33
|
end
|
33
34
|
end
|
@@ -38,13 +39,6 @@ module Kuby
|
|
38
39
|
Kuby::Tasks.new(Kuby.environment)
|
39
40
|
end
|
40
41
|
|
41
|
-
sig { void }
|
42
|
-
def self.must_be_dev_env!
|
43
|
-
unless Kuby.environment.development?
|
44
|
-
fail "Command not supported in the '#{Kuby.environment.name}' environment"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
42
|
program_desc 'Kuby command-line interface. Kuby is a convention '\
|
49
43
|
'over configuration approach for running Rails apps in Kubernetes.'
|
50
44
|
|
@@ -68,59 +62,19 @@ module Kuby
|
|
68
62
|
true
|
69
63
|
end
|
70
64
|
|
71
|
-
# These are only stubs included to fill out the help screens. Rails
|
72
|
-
# commands are handled by the RailsCommands class.
|
73
|
-
desc 'Runs a Rails command.'
|
74
|
-
command :rails do |rc|
|
75
|
-
rc.action do |global_options, options, args|
|
76
|
-
must_be_dev_env!
|
77
|
-
exit 1 unless tasks.dev_deployment_ok
|
78
|
-
@rails_options = T.let(@rails_options, T.nilable(T::Array[String]))
|
79
|
-
Kuby::RailsCommands.run(@rails_options)
|
80
|
-
end
|
81
|
-
|
82
|
-
rc.desc 'Runs the rails server (run `rails server --help` for options)'
|
83
|
-
rc.command [:server, :s] do |c|
|
84
|
-
c.action do |global_options, options, args|
|
85
|
-
must_be_dev_env!
|
86
|
-
exit 1 unless tasks.dev_deployment_ok
|
87
|
-
Kuby::RailsCommands.run(@rails_options)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
rc.desc 'Runs a script in the Rails environment (run `rails runner --help` for options)'
|
92
|
-
rc.command [:runner, :r] do |c|
|
93
|
-
c.action do |global_options, options, args|
|
94
|
-
must_be_dev_env!
|
95
|
-
exit 1 unless tasks.dev_deployment_ok
|
96
|
-
Kuby::RailsCommands.run(@rails_options)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
rc.desc 'Starts an interactive Ruby console with the Rails environment loaded '\
|
101
|
-
'(run `rails console --help` for options)'
|
102
|
-
rc.command [:console, :c] do |c|
|
103
|
-
c.action do |global_options, options, args|
|
104
|
-
must_be_dev_env!
|
105
|
-
exit 1 unless tasks.dev_deployment_ok
|
106
|
-
Kuby::RailsCommands.run(@rails_options)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
desc 'Runs a rake task.'
|
112
|
-
command :rake do |rc|
|
113
|
-
rc.action do |global_options, options, args|
|
114
|
-
must_be_dev_env!
|
115
|
-
exit 1 unless tasks.dev_deployment_ok
|
116
|
-
Kuby::RailsCommands.run(@rails_options)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
65
|
desc 'Builds the Docker image.'
|
121
66
|
command :build do |c|
|
67
|
+
c.flag [:a, :arg], required: false, multiple: true
|
122
68
|
c.action do |global_options, options, args|
|
123
|
-
|
69
|
+
build_args = {}.tap do |build_args|
|
70
|
+
(options[:arg] || []).each do |a|
|
71
|
+
key, value = a.split('=')
|
72
|
+
value = value[1..-2] if value.start_with?('"') || value.start_with?("'")
|
73
|
+
build_args[key] = value
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
tasks.build(build_args)
|
124
78
|
end
|
125
79
|
end
|
126
80
|
|
@@ -138,10 +92,10 @@ module Kuby
|
|
138
92
|
end
|
139
93
|
end
|
140
94
|
|
141
|
-
desc 'Prints the effective
|
142
|
-
command :
|
95
|
+
desc 'Prints the effective Dockerfiles used to build Docker images.'
|
96
|
+
command :dockerfiles do |c|
|
143
97
|
c.action do |global_options, options, args|
|
144
|
-
tasks.
|
98
|
+
tasks.print_dockerfiles
|
145
99
|
end
|
146
100
|
end
|
147
101
|
|
@@ -197,7 +151,6 @@ module Kuby
|
|
197
151
|
rc.desc 'Tails (i.e. continuously streams) the Rails log from your running application.'
|
198
152
|
rc.command :logs do |c|
|
199
153
|
c.action do |global_options, options, args|
|
200
|
-
exit 1 unless tasks.dev_deployment_ok
|
201
154
|
tasks.remote_logs
|
202
155
|
end
|
203
156
|
end
|
@@ -205,7 +158,6 @@ module Kuby
|
|
205
158
|
rc.desc 'Lists running Kubernetes pods.'
|
206
159
|
rc.command :status do |c|
|
207
160
|
c.action do |global_options, options, args|
|
208
|
-
exit 1 unless tasks.dev_deployment_ok
|
209
161
|
tasks.remote_status
|
210
162
|
end
|
211
163
|
end
|
@@ -213,15 +165,13 @@ module Kuby
|
|
213
165
|
rc.desc 'Runs an arbitrary command inside a running Rails pod.'
|
214
166
|
rc.command :exec do |c|
|
215
167
|
c.action do |global_options, options, args|
|
216
|
-
|
217
|
-
tasks.remote_exec(args)
|
168
|
+
tasks.remote_exec([*args, *@rails_options])
|
218
169
|
end
|
219
170
|
end
|
220
171
|
|
221
172
|
rc.desc 'Establishes a shell inside a running Rails pod.'
|
222
173
|
rc.command :shell do |c|
|
223
174
|
c.action do |global_options, options, args|
|
224
|
-
exit 1 unless tasks.dev_deployment_ok
|
225
175
|
tasks.remote_shell
|
226
176
|
end
|
227
177
|
end
|
@@ -229,7 +179,6 @@ module Kuby
|
|
229
179
|
rc.desc 'Establishes a Rails console inside a running Rails pod.'
|
230
180
|
rc.command :console do |c|
|
231
181
|
c.action do |global_options, options, args|
|
232
|
-
exit 1 unless tasks.dev_deployment_ok
|
233
182
|
tasks.remote_console
|
234
183
|
end
|
235
184
|
end
|
@@ -237,7 +186,6 @@ module Kuby
|
|
237
186
|
rc.desc 'Establishes a database console inside a running Rails pod.'
|
238
187
|
rc.command :dbconsole do |c|
|
239
188
|
c.action do |global_options, options, args|
|
240
|
-
exit 1 unless tasks.dev_deployment_ok
|
241
189
|
tasks.remote_dbconsole
|
242
190
|
end
|
243
191
|
end
|
@@ -245,7 +193,6 @@ module Kuby
|
|
245
193
|
rc.desc "Restarts the Rails app's web pods."
|
246
194
|
rc.command :restart do |c|
|
247
195
|
c.action do |global_options, options, args|
|
248
|
-
exit 1 unless tasks.dev_deployment_ok
|
249
196
|
tasks.remote_restart
|
250
197
|
end
|
251
198
|
end
|
data/lib/kuby/docker/alpine.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
# typed: strict
|
3
|
+
|
4
|
+
module Kuby
|
5
|
+
module Docker
|
6
|
+
class AppImage < ::Kuby::Docker::TimestampedImage
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
sig { params(build_args: T::Hash[String, String]).returns(AppImage) }
|
10
|
+
def build(build_args = {})
|
11
|
+
unless ENV.fetch('RAILS_MASTER_KEY', '').empty?
|
12
|
+
build_args['RAILS_MASTER_KEY'] = T.must(ENV['RAILS_MASTER_KEY'])
|
13
|
+
end
|
14
|
+
|
15
|
+
super(build_args)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -35,6 +35,7 @@ module Kuby
|
|
35
35
|
|
36
36
|
@version = T.let(@version, T.nilable(String))
|
37
37
|
@gemfile = T.let(@gemfile, T.nilable(String))
|
38
|
+
@gemfiles = T.let([], T::Array[String])
|
38
39
|
@without = T.let(@without, T.nilable(T::Array[String]))
|
39
40
|
end
|
40
41
|
|
@@ -51,9 +52,9 @@ module Kuby
|
|
51
52
|
dockerfile.copy(gf, '.')
|
52
53
|
dockerfile.copy(lf, '.')
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
55
|
+
@gemfiles.each do |file|
|
56
|
+
dockerfile.copy(file, file)
|
57
|
+
end
|
57
58
|
|
58
59
|
unless wo.empty?
|
59
60
|
dockerfile.env("BUNDLE_WITHOUT='#{wo.join(' ')}'")
|
@@ -71,6 +72,11 @@ module Kuby
|
|
71
72
|
dockerfile.env("PATH=./bin:$PATH")
|
72
73
|
end
|
73
74
|
|
75
|
+
sig { params(paths: String).void }
|
76
|
+
def gemfiles(*paths)
|
77
|
+
@gemfiles.concat(paths)
|
78
|
+
end
|
79
|
+
|
74
80
|
private
|
75
81
|
|
76
82
|
sig { returns(String) }
|
data/lib/kuby/docker/cli.rb
CHANGED
@@ -53,19 +53,11 @@ module Kuby
|
|
53
53
|
config.fetch('auths', {}).keys
|
54
54
|
end
|
55
55
|
|
56
|
-
sig {
|
57
|
-
|
58
|
-
dockerfile: Dockerfile,
|
59
|
-
image_url: String,
|
60
|
-
tags: T::Array[String],
|
61
|
-
build_args: T::Hash[T.any(Symbol, String), String]
|
62
|
-
)
|
63
|
-
.void
|
64
|
-
}
|
65
|
-
def build(dockerfile:, image_url:, tags:, build_args: {})
|
56
|
+
sig { params(image: Image, build_args: T::Hash[T.any(Symbol, String), String]).void }
|
57
|
+
def build(image, build_args: {})
|
66
58
|
cmd = [
|
67
59
|
executable, 'build',
|
68
|
-
*tags.flat_map { |tag| ['-t', "#{image_url}:#{tag}"] },
|
60
|
+
*image.tags.flat_map { |tag| ['-t', "#{image.image_url}:#{tag}"] },
|
69
61
|
*build_args.flat_map do |arg, val|
|
70
62
|
['--build-arg', Shellwords.shellescape("#{arg}=#{val}")]
|
71
63
|
end,
|
@@ -73,7 +65,7 @@ module Kuby
|
|
73
65
|
]
|
74
66
|
|
75
67
|
open3_w(cmd) do |stdin, _wait_threads|
|
76
|
-
stdin.puts(dockerfile.to_s)
|
68
|
+
stdin.puts(image.dockerfile.to_s)
|
77
69
|
end
|
78
70
|
|
79
71
|
unless T.must(last_status).success?
|
@@ -1,11 +1,14 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
|
3
3
|
module Kuby
|
4
4
|
module Docker
|
5
5
|
class DockerURI
|
6
|
-
|
7
|
-
DEFAULT_REGISTRY_PORT = 443
|
6
|
+
extend T::Sig
|
8
7
|
|
8
|
+
DEFAULT_REGISTRY_HOST = T.let('index.docker.io'.freeze, String)
|
9
|
+
DEFAULT_REGISTRY_PORT = T.let(443, Integer)
|
10
|
+
|
11
|
+
sig { params(url: String).returns(DockerURI) }
|
9
12
|
def self.parse(url)
|
10
13
|
if idx = url.index('://')
|
11
14
|
url = url[(idx + 3)..-1] || ''
|
@@ -13,17 +16,25 @@ module Kuby
|
|
13
16
|
|
14
17
|
host_port, *path = url.split('/')
|
15
18
|
host, port, *path = if host_port =~ /[.:]/
|
16
|
-
hst, prt = host_port.split(':')
|
17
|
-
[hst, prt || DEFAULT_REGISTRY_PORT, *path]
|
19
|
+
hst, prt = T.must(host_port).split(':')
|
20
|
+
[T.must(hst), prt || DEFAULT_REGISTRY_PORT, *path]
|
18
21
|
else
|
19
22
|
[DEFAULT_REGISTRY_HOST, DEFAULT_REGISTRY_PORT, host_port, *path]
|
20
23
|
end
|
21
24
|
|
22
|
-
new(host, port.to_i, path.join('/'))
|
25
|
+
new(host.to_s, port.to_i, (path || []).join('/'))
|
23
26
|
end
|
24
27
|
|
25
|
-
|
28
|
+
sig { returns(String) }
|
29
|
+
attr_reader :host
|
30
|
+
|
31
|
+
sig { returns(Integer) }
|
32
|
+
attr_reader :port
|
33
|
+
|
34
|
+
sig { returns(String) }
|
35
|
+
attr_reader :path
|
26
36
|
|
37
|
+
sig { params(host: String, port: Integer, path: String).void }
|
27
38
|
def initialize(host, port, path)
|
28
39
|
@host = host
|
29
40
|
@port = port
|
data/lib/kuby/docker/errors.rb
CHANGED
@@ -6,25 +6,7 @@ module Kuby
|
|
6
6
|
class PushError < StandardError; end
|
7
7
|
class PullError < StandardError; end
|
8
8
|
class LoginError < StandardError; end
|
9
|
-
|
10
|
-
class MissingTagError < StandardError
|
11
|
-
extend T::Sig
|
12
|
-
|
13
|
-
sig { returns(String) }
|
14
|
-
attr_reader :tag
|
15
|
-
|
16
|
-
sig { params(tag: String).void }
|
17
|
-
def initialize(tag)
|
18
|
-
@tag = tag
|
19
|
-
@message = T.let(@message, T.nilable(String))
|
20
|
-
end
|
21
|
-
|
22
|
-
sig { returns(String) }
|
23
|
-
def message
|
24
|
-
@message ||= "Could not find tag '#{tag}'."
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
9
|
+
class MissingTagError < StandardError; end
|
28
10
|
class UnsupportedDistroError < StandardError; end
|
29
11
|
class MissingPackageError < StandardError; end
|
30
12
|
class MissingDistroError < StandardError; end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module Kuby
|
4
|
+
module Docker
|
5
|
+
class Image
|
6
|
+
extend T::Sig
|
7
|
+
|
8
|
+
sig { returns(String) }
|
9
|
+
attr_reader :image_url
|
10
|
+
|
11
|
+
sig { returns(Credentials) }
|
12
|
+
attr_reader :credentials
|
13
|
+
|
14
|
+
sig { returns(T.nilable(String)) }
|
15
|
+
attr_reader :main_tag
|
16
|
+
|
17
|
+
sig { returns T::Array[String] }
|
18
|
+
attr_reader :alias_tags
|
19
|
+
|
20
|
+
sig {
|
21
|
+
params(
|
22
|
+
dockerfile: T.any(Dockerfile, T.proc.returns(Dockerfile)),
|
23
|
+
image_url: String,
|
24
|
+
credentials: Credentials,
|
25
|
+
main_tag: T.nilable(String),
|
26
|
+
alias_tags: T::Array[String]
|
27
|
+
).void
|
28
|
+
}
|
29
|
+
def initialize(dockerfile, image_url, credentials, main_tag = nil, alias_tags = [])
|
30
|
+
@dockerfile = T.let(dockerfile, T.any(Dockerfile, T.proc.returns(Dockerfile)))
|
31
|
+
@image_url = T.let(image_url, String)
|
32
|
+
@credentials = T.let(credentials, Credentials)
|
33
|
+
@main_tag = T.let(main_tag, T.nilable(String))
|
34
|
+
@alias_tags = T.let(alias_tags, T::Array[String])
|
35
|
+
|
36
|
+
@image_host = T.let(@image_host, T.nilable(String))
|
37
|
+
@image_hostname = T.let(@image_hostname, T.nilable(String))
|
38
|
+
@image_repo = T.let(@image_repo, T.nilable(String))
|
39
|
+
@full_image_uri = T.let(@full_image_uri, T.nilable(DockerURI))
|
40
|
+
@docker_cli = T.let(@docker_cli, T.nilable(Docker::CLI))
|
41
|
+
end
|
42
|
+
|
43
|
+
sig { returns(Image) }
|
44
|
+
def new_version
|
45
|
+
raise NotImplementedError, 'please use a Docker::Image subclass'
|
46
|
+
end
|
47
|
+
|
48
|
+
sig { returns(Image) }
|
49
|
+
def current_version
|
50
|
+
raise NotImplementedError, 'please use a Docker::Image subclass'
|
51
|
+
end
|
52
|
+
|
53
|
+
sig { params(current_tag: T.nilable(String)).returns(Image) }
|
54
|
+
def previous_version(current_tag = nil)
|
55
|
+
raise NotImplementedError, 'please use a Docker::Image subclass'
|
56
|
+
end
|
57
|
+
|
58
|
+
sig { returns(Dockerfile) }
|
59
|
+
def dockerfile
|
60
|
+
if @dockerfile.respond_to?(:call)
|
61
|
+
T.cast(@dockerfile, T.proc.returns(Dockerfile)).call
|
62
|
+
else
|
63
|
+
T.cast(@dockerfile, Dockerfile)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
sig { returns(String) }
|
68
|
+
def image_host
|
69
|
+
@image_host ||= "#{image_uri.host}:#{image_uri.port}"
|
70
|
+
end
|
71
|
+
|
72
|
+
sig { returns(String) }
|
73
|
+
def image_hostname
|
74
|
+
@image_hostname ||= image_uri.host
|
75
|
+
end
|
76
|
+
|
77
|
+
sig { returns(String) }
|
78
|
+
def image_repo
|
79
|
+
@image_repo ||= image_uri.path
|
80
|
+
end
|
81
|
+
|
82
|
+
sig { returns(DockerURI) }
|
83
|
+
def image_uri
|
84
|
+
@full_image_uri ||= DockerURI.parse(image_url)
|
85
|
+
end
|
86
|
+
|
87
|
+
sig { returns(T::Array[String]) }
|
88
|
+
def tags
|
89
|
+
[main_tag, *alias_tags].compact
|
90
|
+
end
|
91
|
+
|
92
|
+
sig { params(build_args: T::Hash[String, String]).void }
|
93
|
+
def build(build_args = {})
|
94
|
+
raise NotImplementedError, 'please use a Docker::Image subclass'
|
95
|
+
end
|
96
|
+
|
97
|
+
sig { params(tag: String).void }
|
98
|
+
def push(tag)
|
99
|
+
raise NotImplementedError, 'please use a Docker::Image subclass'
|
100
|
+
end
|
101
|
+
|
102
|
+
sig { returns(Docker::CLI) }
|
103
|
+
def docker_cli
|
104
|
+
@docker_cli ||= Docker::CLI.new
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
sig { params(main_tag: String, alias_tags: T::Array[String]).returns(Image) }
|
110
|
+
def duplicate_with_tags(main_tag, alias_tags)
|
111
|
+
self.class.new(dockerfile, image_url, credentials, main_tag, alias_tags)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
data/lib/kuby/docker/layer.rb
CHANGED
@@ -8,37 +8,36 @@ module Kuby
|
|
8
8
|
sig { returns CLI }
|
9
9
|
attr_reader :cli
|
10
10
|
|
11
|
-
sig { returns(
|
12
|
-
attr_reader :
|
11
|
+
sig { returns(String) }
|
12
|
+
attr_reader :image_url
|
13
13
|
|
14
14
|
sig {
|
15
15
|
params(
|
16
16
|
cli: CLI,
|
17
|
-
|
17
|
+
image_url: String
|
18
18
|
)
|
19
19
|
.void
|
20
20
|
}
|
21
|
-
def initialize(cli,
|
21
|
+
def initialize(cli, image_url)
|
22
22
|
@cli = cli
|
23
|
-
@
|
24
|
-
|
23
|
+
@image_url = image_url
|
25
24
|
@latest_timestamp_tag = T.let(@latest_timestamp_tag, T.nilable(TimestampTag))
|
26
25
|
end
|
27
26
|
|
28
27
|
sig { returns(T::Array[String]) }
|
29
28
|
def tags
|
30
|
-
images = cli.images(
|
29
|
+
images = cli.images(image_url)
|
31
30
|
images.map { |image| T.must(image[:tag]) }
|
32
31
|
end
|
33
32
|
|
34
33
|
sig { returns(T::Array[String]) }
|
35
34
|
def latest_tags
|
36
35
|
# find "latest" tag
|
37
|
-
images = cli.images(
|
38
|
-
latest = images.find { |image| image[:tag] ==
|
36
|
+
images = cli.images(image_url)
|
37
|
+
latest = images.find { |image| image[:tag] == Kuby::Docker::LATEST_TAG }
|
39
38
|
|
40
39
|
unless latest
|
41
|
-
raise MissingTagError
|
40
|
+
raise MissingTagError, "could not find tag #{Kuby::Docker::LATEST_TAG}"
|
42
41
|
end
|
43
42
|
|
44
43
|
# find all tags that point to the same image as 'latest'
|