kuby-core 0.11.16 → 0.15.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 +35 -0
- data/Gemfile +1 -2
- data/README.md +2 -1
- data/kuby-core.gemspec +1 -1
- data/lib/kuby/commands.rb +25 -73
- data/lib/kuby/docker/alpine.rb +2 -1
- data/lib/kuby/docker/app_image.rb +34 -0
- data/lib/kuby/docker/bundler_phase.rb +10 -0
- data/lib/kuby/docker/cli.rb +7 -13
- data/lib/kuby/docker/docker_uri.rb +50 -9
- data/lib/kuby/docker/errors.rb +1 -19
- data/lib/kuby/docker/image.rb +142 -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 +38 -62
- data/lib/kuby/docker/timestamp_tag.rb +8 -1
- data/lib/kuby/docker/timestamped_image.rb +114 -0
- data/lib/kuby/docker.rb +27 -25
- data/lib/kuby/environment.rb +1 -10
- data/lib/kuby/kubernetes/bare_metal_provider.rb +16 -4
- data/lib/kuby/kubernetes/deployer.rb +1 -1
- data/lib/kuby/kubernetes/docker_desktop_provider.rb +0 -15
- data/lib/kuby/kubernetes/spec.rb +21 -17
- data/lib/kuby/plugin.rb +2 -2
- data/lib/kuby/plugins/rails_app/assets.rb +62 -70
- data/lib/kuby/plugins/rails_app/assets_image.rb +57 -0
- data/lib/kuby/plugins/rails_app/generators/kuby.rb +31 -9
- data/lib/kuby/plugins/rails_app/plugin.rb +53 -236
- data/lib/kuby/plugins/rails_app.rb +1 -0
- data/lib/kuby/tasks.rb +98 -69
- data/lib/kuby/version.rb +1 -1
- data/lib/kuby.rb +2 -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 +10 -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: 0a5f265cee423b7487de7e4c209b26cc9fef63cf584455bc4164ecd7e6384377
|
4
|
+
data.tar.gz: e48304bf9397b30ceed7025039d074e55423ced190f734a416a311e412bd609d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4cbd6c2fbf6de8f621d4b2412bb4c1921eff7e5ba3c90b5afefac3c0d216aff676772b0582dab70a688c3c1dc7ce55a48f9c42f3b178ad25f31d489a3f33421
|
7
|
+
data.tar.gz: b9b3f808ed6184c73edb8652a958cd53b12337c8a48bf2f19d188b07c1c4d56283f7bfbfffd2a9338dc522a2376f8665e9c792571b4fdb609bf14b0181efcc16
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,38 @@
|
|
1
|
+
## 0.15.0
|
2
|
+
* Add an extra parameter to the Docker spec for specifying the URL of the Docker registry index.
|
3
|
+
- In most cases, the registry and registry index URLs will be the same. However Docker Hub, the default registry, uses index.docker.io for API requests (catalog, tags, etc) but only allows pushes to docker.io.
|
4
|
+
* Add config/master.key to the .dockerignore created by the Rails generator.
|
5
|
+
- This was an unfortunate oversight, but such are the perils of using pre-1.0 software.
|
6
|
+
* Print an error message if building images on non-x86 hardware.
|
7
|
+
- People with M1 Macs are running into mismatches between their laptop's arch and the arch of their hosting provider's hardware. The error message asks you to explicitly pass the `--platform` flag to Docker.
|
8
|
+
- We may need to revisit this in the future if ARM processors become more popular.
|
9
|
+
|
10
|
+
## 0.14.0
|
11
|
+
* Make RAILS_MASTER_KEY available in the assets image (@palkan, #63)
|
12
|
+
* Allow specifying custom docker build options via CLI (@palkan, #65)
|
13
|
+
|
14
|
+
## 0.13.0
|
15
|
+
* Fix handling rails/rake options in remote exec (@palkan, #60)
|
16
|
+
* Add `bundler_phase.gemfiles(*paths)` to allow adding additional gemfiles (@palkan, #61)
|
17
|
+
|
18
|
+
## 0.12.0
|
19
|
+
* Fix issue causing volume mount errors when k8s tries to schedule asset pods on multiple nodes (fixes #42).
|
20
|
+
- Persistent volumes can only be mounted on a single physical node.
|
21
|
+
- Kuby now creates a separate assets image powered by nginx.
|
22
|
+
- Ingress routes requests to either the Rails service or assets service depending on the URL (i.e. /assets).
|
23
|
+
- 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.
|
24
|
+
* Plugins can now specify additional Dockerfiles to build during `kuby build`.
|
25
|
+
* Switch from TravisCI to Github Actions.
|
26
|
+
* Remove support for development environments.
|
27
|
+
- Proved to be too difficult to maintain.
|
28
|
+
- Kuby is a _deployment_ tool anyway, not a dev tool.
|
29
|
+
- Maybe we can turn the dev stuff into a gem at some point.
|
30
|
+
* Refactor Docker image logic.
|
31
|
+
- Introduced the `Image` class and friends.
|
32
|
+
- Deleted the `Kuby::Docker::Metadata` class.
|
33
|
+
* Add missing git dependency to Alpine distro.
|
34
|
+
* Add a bare metal provider (fixes #10).
|
35
|
+
|
1
36
|
## 0.11.16
|
2
37
|
* Fix yarn phase
|
3
38
|
- Apparently you have to copy at least one file, TIL.
|
data/Gemfile
CHANGED
@@ -6,10 +6,9 @@ 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.
|
9
|
+
gem 'sorbet', '= 0.5.6433'
|
10
10
|
end
|
11
11
|
|
12
12
|
group :test do
|
13
13
|
gem 'rspec', '~> 3.0'
|
14
|
-
gem 'timecop', '~> 0.9'
|
15
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/kuby-core.gemspec
CHANGED
@@ -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/commands.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: false
|
2
2
|
|
3
3
|
require 'kuby/version'
|
4
4
|
require 'gli'
|
@@ -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,66 +62,28 @@ 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|
|
122
|
-
c.
|
123
|
-
|
67
|
+
c.flag [:a, :arg], required: false, multiple: true
|
68
|
+
c.flag [:only], required: false
|
69
|
+
c.action do |global_options, options, docker_args|
|
70
|
+
build_args = {}.tap do |build_args|
|
71
|
+
(options[:arg] || []).each do |a|
|
72
|
+
key, value = a.split('=', 2)
|
73
|
+
value = value[1..-2] if value.start_with?('"') || value.start_with?("'")
|
74
|
+
build_args[key] = value
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
tasks.build(build_args, docker_args, options[:only])
|
124
79
|
end
|
125
80
|
end
|
126
81
|
|
127
82
|
desc 'Pushes the Docker image to the configured registry.'
|
128
83
|
command :push do |c|
|
84
|
+
c.flag [:only], required: false
|
129
85
|
c.action do |global_options, options, args|
|
130
|
-
tasks.push
|
86
|
+
tasks.push(options[:only])
|
131
87
|
end
|
132
88
|
end
|
133
89
|
|
@@ -138,10 +94,11 @@ module Kuby
|
|
138
94
|
end
|
139
95
|
end
|
140
96
|
|
141
|
-
desc 'Prints the effective
|
142
|
-
command :
|
97
|
+
desc 'Prints the effective Dockerfiles used to build Docker images.'
|
98
|
+
command :dockerfiles do |c|
|
99
|
+
c.flag [:only], required: false
|
143
100
|
c.action do |global_options, options, args|
|
144
|
-
tasks.
|
101
|
+
tasks.print_dockerfiles(options[:only])
|
145
102
|
end
|
146
103
|
end
|
147
104
|
|
@@ -163,8 +120,10 @@ module Kuby
|
|
163
120
|
|
164
121
|
desc 'Prints the effective Kubernetes resources that will be applied on deploy.'
|
165
122
|
command :resources do |c|
|
123
|
+
c.flag [:K, :kind], required: false
|
124
|
+
c.flag [:N, :name], required: false
|
166
125
|
c.action do |global_options, options, args|
|
167
|
-
tasks.print_resources
|
126
|
+
tasks.print_resources(options[:kind], options[:name])
|
168
127
|
end
|
169
128
|
end
|
170
129
|
|
@@ -197,7 +156,6 @@ module Kuby
|
|
197
156
|
rc.desc 'Tails (i.e. continuously streams) the Rails log from your running application.'
|
198
157
|
rc.command :logs do |c|
|
199
158
|
c.action do |global_options, options, args|
|
200
|
-
exit 1 unless tasks.dev_deployment_ok
|
201
159
|
tasks.remote_logs
|
202
160
|
end
|
203
161
|
end
|
@@ -205,7 +163,6 @@ module Kuby
|
|
205
163
|
rc.desc 'Lists running Kubernetes pods.'
|
206
164
|
rc.command :status do |c|
|
207
165
|
c.action do |global_options, options, args|
|
208
|
-
exit 1 unless tasks.dev_deployment_ok
|
209
166
|
tasks.remote_status
|
210
167
|
end
|
211
168
|
end
|
@@ -213,15 +170,13 @@ module Kuby
|
|
213
170
|
rc.desc 'Runs an arbitrary command inside a running Rails pod.'
|
214
171
|
rc.command :exec do |c|
|
215
172
|
c.action do |global_options, options, args|
|
216
|
-
|
217
|
-
tasks.remote_exec(args)
|
173
|
+
tasks.remote_exec([*args, *T.unsafe(@rails_options)])
|
218
174
|
end
|
219
175
|
end
|
220
176
|
|
221
177
|
rc.desc 'Establishes a shell inside a running Rails pod.'
|
222
178
|
rc.command :shell do |c|
|
223
179
|
c.action do |global_options, options, args|
|
224
|
-
exit 1 unless tasks.dev_deployment_ok
|
225
180
|
tasks.remote_shell
|
226
181
|
end
|
227
182
|
end
|
@@ -229,7 +184,6 @@ module Kuby
|
|
229
184
|
rc.desc 'Establishes a Rails console inside a running Rails pod.'
|
230
185
|
rc.command :console do |c|
|
231
186
|
c.action do |global_options, options, args|
|
232
|
-
exit 1 unless tasks.dev_deployment_ok
|
233
187
|
tasks.remote_console
|
234
188
|
end
|
235
189
|
end
|
@@ -237,7 +191,6 @@ module Kuby
|
|
237
191
|
rc.desc 'Establishes a database console inside a running Rails pod.'
|
238
192
|
rc.command :dbconsole do |c|
|
239
193
|
c.action do |global_options, options, args|
|
240
|
-
exit 1 unless tasks.dev_deployment_ok
|
241
194
|
tasks.remote_dbconsole
|
242
195
|
end
|
243
196
|
end
|
@@ -245,7 +198,6 @@ module Kuby
|
|
245
198
|
rc.desc "Restarts the Rails app's web pods."
|
246
199
|
rc.command :restart do |c|
|
247
200
|
c.action do |global_options, options, args|
|
248
|
-
exit 1 unless tasks.dev_deployment_ok
|
249
201
|
tasks.remote_restart
|
250
202
|
end
|
251
203
|
end
|
data/lib/kuby/docker/alpine.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
# typed: strict
|
3
|
+
|
4
|
+
module Kuby
|
5
|
+
module Docker
|
6
|
+
class AppImage < ::Kuby::Docker::TimestampedImage
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
sig {
|
10
|
+
params(
|
11
|
+
dockerfile: T.any(Dockerfile, T.proc.returns(Dockerfile)),
|
12
|
+
image_url: String,
|
13
|
+
credentials: Credentials,
|
14
|
+
registry_index_url: T.nilable(String),
|
15
|
+
main_tag: T.nilable(String),
|
16
|
+
alias_tags: T::Array[String]
|
17
|
+
).void
|
18
|
+
}
|
19
|
+
def initialize(dockerfile, image_url, credentials, registry_index_url = nil, main_tag = nil, alias_tags = [])
|
20
|
+
super
|
21
|
+
@identifier = "app"
|
22
|
+
end
|
23
|
+
|
24
|
+
sig { params(build_args: T::Hash[String, String], docker_args: T::Array[String]).returns(AppImage) }
|
25
|
+
def build(build_args = {}, docker_args = [])
|
26
|
+
unless ENV.fetch('RAILS_MASTER_KEY', '').empty?
|
27
|
+
build_args['RAILS_MASTER_KEY'] = T.must(ENV['RAILS_MASTER_KEY'])
|
28
|
+
end
|
29
|
+
|
30
|
+
super(build_args, docker_args)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
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,6 +52,10 @@ module Kuby
|
|
51
52
|
dockerfile.copy(gf, '.')
|
52
53
|
dockerfile.copy(lf, '.')
|
53
54
|
|
55
|
+
@gemfiles.each do |file|
|
56
|
+
dockerfile.copy(file, file)
|
57
|
+
end
|
58
|
+
|
54
59
|
unless wo.empty?
|
55
60
|
dockerfile.env("BUNDLE_WITHOUT='#{wo.join(' ')}'")
|
56
61
|
end
|
@@ -67,6 +72,11 @@ module Kuby
|
|
67
72
|
dockerfile.env("PATH=./bin:$PATH")
|
68
73
|
end
|
69
74
|
|
75
|
+
sig { params(paths: String).void }
|
76
|
+
def gemfiles(*paths)
|
77
|
+
@gemfiles.concat(paths)
|
78
|
+
end
|
79
|
+
|
70
80
|
private
|
71
81
|
|
72
82
|
sig { returns(String) }
|
data/lib/kuby/docker/cli.rb
CHANGED
@@ -53,27 +53,21 @@ 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], docker_args: T::Array[String]).void }
|
57
|
+
def build(image, build_args: {}, docker_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,
|
72
|
-
'-f-',
|
64
|
+
'-f-',
|
65
|
+
*docker_args,
|
66
|
+
'.'
|
73
67
|
]
|
74
68
|
|
75
69
|
open3_w(cmd) do |stdin, _wait_threads|
|
76
|
-
stdin.puts(dockerfile.to_s)
|
70
|
+
stdin.puts(image.dockerfile.to_s)
|
77
71
|
end
|
78
72
|
|
79
73
|
unless T.must(last_status).success?
|
@@ -1,34 +1,75 @@
|
|
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
|
|
9
|
-
|
8
|
+
DEFAULT_REGISTRY_HOST = T.let('docker.io'.freeze, String)
|
9
|
+
DEFAULT_REGISTRY_INDEX_HOST = T.let('index.docker.io'.freeze, String)
|
10
|
+
DEFAULT_PORT = T.let(443, Integer)
|
11
|
+
|
12
|
+
sig { params(url: String).returns(DockerURI) }
|
13
|
+
def self.parse_uri(url)
|
14
|
+
parse(
|
15
|
+
url,
|
16
|
+
default_host: DEFAULT_REGISTRY_HOST,
|
17
|
+
default_port: DEFAULT_PORT
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
sig { params(url: String).returns(DockerURI) }
|
22
|
+
def self.parse_index_uri(url)
|
23
|
+
parse(
|
24
|
+
url,
|
25
|
+
default_host: DEFAULT_REGISTRY_INDEX_HOST,
|
26
|
+
default_port: DEFAULT_PORT
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
sig {
|
31
|
+
params(
|
32
|
+
url: String,
|
33
|
+
default_host: T.nilable(String),
|
34
|
+
default_port: T.nilable(Integer)
|
35
|
+
).returns(DockerURI)
|
36
|
+
}
|
37
|
+
def self.parse(url, default_host:, default_port:)
|
10
38
|
if idx = url.index('://')
|
11
39
|
url = url[(idx + 3)..-1] || ''
|
12
40
|
end
|
13
41
|
|
14
42
|
host_port, *path = url.split('/')
|
15
43
|
host, port, *path = if host_port =~ /[.:]/
|
16
|
-
hst, prt = host_port.split(':')
|
17
|
-
[hst, prt ||
|
44
|
+
hst, prt = T.must(host_port).split(':')
|
45
|
+
[T.must(hst), prt || default_port, *path]
|
18
46
|
else
|
19
|
-
[
|
47
|
+
[default_host, default_port, host_port, *path]
|
20
48
|
end
|
21
49
|
|
22
|
-
new(host, port.to_i, path.join('/'))
|
50
|
+
new(host.to_s, port.to_i, (path || []).join('/'))
|
23
51
|
end
|
24
52
|
|
25
|
-
|
53
|
+
sig { returns(String) }
|
54
|
+
attr_reader :host
|
26
55
|
|
56
|
+
sig { returns(Integer) }
|
57
|
+
attr_reader :port
|
58
|
+
|
59
|
+
sig { returns(String) }
|
60
|
+
attr_reader :path
|
61
|
+
|
62
|
+
sig { params(host: String, port: Integer, path: String).void }
|
27
63
|
def initialize(host, port, path)
|
28
64
|
@host = host
|
29
65
|
@port = port
|
30
66
|
@path = path
|
31
67
|
end
|
68
|
+
|
69
|
+
sig { returns(T::Boolean) }
|
70
|
+
def has_default_port?
|
71
|
+
port == DEFAULT_PORT
|
72
|
+
end
|
32
73
|
end
|
33
74
|
end
|
34
75
|
end
|
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,142 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module Kuby
|
4
|
+
module Docker
|
5
|
+
class Image
|
6
|
+
extend T::Sig
|
7
|
+
|
8
|
+
sig { returns(T.nilable(String)) }
|
9
|
+
attr_reader :identifier
|
10
|
+
|
11
|
+
sig { returns(String) }
|
12
|
+
attr_reader :image_url
|
13
|
+
|
14
|
+
sig { returns(T.nilable(String)) }
|
15
|
+
attr_reader :registry_index_url
|
16
|
+
|
17
|
+
sig { returns(Credentials) }
|
18
|
+
attr_reader :credentials
|
19
|
+
|
20
|
+
sig { returns(T.nilable(String)) }
|
21
|
+
attr_reader :main_tag
|
22
|
+
|
23
|
+
sig { returns T::Array[String] }
|
24
|
+
attr_reader :alias_tags
|
25
|
+
|
26
|
+
sig {
|
27
|
+
params(
|
28
|
+
dockerfile: T.any(Dockerfile, T.proc.returns(Dockerfile)),
|
29
|
+
image_url: String,
|
30
|
+
credentials: Credentials,
|
31
|
+
registry_index_url: T.nilable(String),
|
32
|
+
main_tag: T.nilable(String),
|
33
|
+
alias_tags: T::Array[String]
|
34
|
+
).void
|
35
|
+
}
|
36
|
+
def initialize(dockerfile, image_url, credentials, registry_index_url = nil, main_tag = nil, alias_tags = [])
|
37
|
+
@dockerfile = T.let(dockerfile, T.any(Dockerfile, T.proc.returns(Dockerfile)))
|
38
|
+
@image_url = T.let(image_url, String)
|
39
|
+
@registry_index_url = T.let(registry_index_url, T.nilable(String))
|
40
|
+
@credentials = T.let(credentials, Credentials)
|
41
|
+
@main_tag = T.let(main_tag, T.nilable(String))
|
42
|
+
@alias_tags = T.let(alias_tags, T::Array[String])
|
43
|
+
@identifier = T.let(@identifier, T.nilable(String))
|
44
|
+
|
45
|
+
@image_host = T.let(@image_host, T.nilable(String))
|
46
|
+
@image_hostname = T.let(@image_hostname, T.nilable(String))
|
47
|
+
@registry_index_host = T.let(@registry_index_host, T.nilable(String))
|
48
|
+
@registry_index_hostname = T.let(@registry_index_hostname, T.nilable(String))
|
49
|
+
@registry_index_uri = T.let(@registry_index_uri, T.nilable(DockerURI))
|
50
|
+
@image_repo = T.let(@image_repo, T.nilable(String))
|
51
|
+
@full_image_uri = T.let(@full_image_uri, T.nilable(DockerURI))
|
52
|
+
@docker_cli = T.let(@docker_cli, T.nilable(Docker::CLI))
|
53
|
+
end
|
54
|
+
|
55
|
+
sig { returns(Image) }
|
56
|
+
def new_version
|
57
|
+
raise NotImplementedError, 'please use a Docker::Image subclass'
|
58
|
+
end
|
59
|
+
|
60
|
+
sig { returns(Image) }
|
61
|
+
def current_version
|
62
|
+
raise NotImplementedError, 'please use a Docker::Image subclass'
|
63
|
+
end
|
64
|
+
|
65
|
+
sig { params(current_tag: T.nilable(String)).returns(Image) }
|
66
|
+
def previous_version(current_tag = nil)
|
67
|
+
raise NotImplementedError, 'please use a Docker::Image subclass'
|
68
|
+
end
|
69
|
+
|
70
|
+
sig { returns(Dockerfile) }
|
71
|
+
def dockerfile
|
72
|
+
if @dockerfile.respond_to?(:call)
|
73
|
+
T.cast(@dockerfile, T.proc.returns(Dockerfile)).call
|
74
|
+
else
|
75
|
+
T.cast(@dockerfile, Dockerfile)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
sig { returns(String) }
|
80
|
+
def image_host
|
81
|
+
@image_host ||= "#{image_uri.host}:#{image_uri.port}"
|
82
|
+
end
|
83
|
+
|
84
|
+
sig { returns(String) }
|
85
|
+
def registry_index_host
|
86
|
+
@registry_index_host ||= "#{registry_index_uri.host}:#{registry_index_uri.port}"
|
87
|
+
end
|
88
|
+
|
89
|
+
sig { returns(String) }
|
90
|
+
def registry_index_hostname
|
91
|
+
@registry_index_hostname ||= registry_index_uri.host
|
92
|
+
end
|
93
|
+
|
94
|
+
sig { returns(String) }
|
95
|
+
def image_hostname
|
96
|
+
@image_hostname ||= image_uri.host
|
97
|
+
end
|
98
|
+
|
99
|
+
sig { returns(String) }
|
100
|
+
def image_repo
|
101
|
+
@image_repo ||= image_uri.path
|
102
|
+
end
|
103
|
+
|
104
|
+
sig { returns(DockerURI) }
|
105
|
+
def image_uri
|
106
|
+
@full_image_uri ||= DockerURI.parse_uri(image_url)
|
107
|
+
end
|
108
|
+
|
109
|
+
sig { returns(DockerURI) }
|
110
|
+
def registry_index_uri
|
111
|
+
@registry_index_uri ||= DockerURI.parse_index_uri(registry_index_url || image_url)
|
112
|
+
end
|
113
|
+
|
114
|
+
sig { returns(T::Array[String]) }
|
115
|
+
def tags
|
116
|
+
[main_tag, *alias_tags].compact
|
117
|
+
end
|
118
|
+
|
119
|
+
sig { params(build_args: T::Hash[String, String], docker_args: T::Array[String]).void }
|
120
|
+
def build(build_args = {}, docker_args = [])
|
121
|
+
raise NotImplementedError, 'please use a Docker::Image subclass'
|
122
|
+
end
|
123
|
+
|
124
|
+
sig { params(tag: String).void }
|
125
|
+
def push(tag)
|
126
|
+
raise NotImplementedError, 'please use a Docker::Image subclass'
|
127
|
+
end
|
128
|
+
|
129
|
+
sig { returns(Docker::CLI) }
|
130
|
+
def docker_cli
|
131
|
+
@docker_cli ||= Docker::CLI.new
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
sig { params(main_tag: String, alias_tags: T::Array[String]).returns(Image) }
|
137
|
+
def duplicate_with_tags(main_tag, alias_tags)
|
138
|
+
self.class.new(dockerfile, image_url, credentials, registry_index_url, main_tag, alias_tags)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
data/lib/kuby/docker/layer.rb
CHANGED