kuby-core 0.16.0 → 0.18.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 +58 -0
- data/Gemfile +6 -2
- data/Rakefile +5 -3
- data/bin/tapioca +29 -0
- data/kuby-core.gemspec +9 -11
- data/lib/kuby/basic_logger.rb +34 -34
- data/lib/kuby/cli_base.rb +43 -43
- data/lib/kuby/commands.rb +135 -21
- data/lib/kuby/definition.rb +12 -12
- data/lib/kuby/dependable.rb +20 -0
- data/lib/kuby/dependency.rb +14 -0
- data/lib/kuby/docker/alpine.rb +10 -10
- data/lib/kuby/docker/app_image.rb +11 -20
- data/lib/kuby/docker/app_phase.rb +36 -0
- data/lib/kuby/docker/assets_phase.rb +2 -2
- data/lib/kuby/docker/bundler_phase.rb +42 -40
- data/lib/kuby/docker/cli.rb +72 -37
- data/lib/kuby/docker/copy_phase.rb +7 -7
- data/lib/kuby/docker/credentials.rb +1 -0
- data/lib/kuby/docker/debian.rb +10 -10
- data/lib/kuby/docker/distro.rb +13 -13
- data/lib/kuby/docker/docker_uri.rb +20 -20
- data/lib/kuby/docker/dockerfile.rb +48 -39
- data/lib/kuby/docker/image.rb +66 -54
- data/lib/kuby/docker/inline_layer.rb +4 -4
- data/lib/kuby/docker/layer.rb +6 -6
- data/lib/kuby/docker/layer_stack.rb +35 -35
- data/lib/kuby/docker/local_tags.rb +16 -16
- data/lib/kuby/docker/package_list.rb +16 -16
- data/lib/kuby/docker/package_phase.rb +16 -16
- data/lib/kuby/docker/packages/managed_package.rb +13 -13
- data/lib/kuby/docker/packages/nodejs.rb +5 -5
- data/lib/kuby/docker/packages/package.rb +8 -8
- data/lib/kuby/docker/packages/simple_managed_package.rb +7 -7
- data/lib/kuby/docker/packages/yarn.rb +6 -6
- data/lib/kuby/docker/remote_tags.rb +16 -16
- data/lib/kuby/docker/setup_phase.rb +18 -20
- data/lib/kuby/docker/spec.rb +93 -72
- data/lib/kuby/docker/timestamp_tag.rb +16 -11
- data/lib/kuby/docker/timestamped_image.rb +64 -38
- data/lib/kuby/docker/webserver_phase.rb +20 -20
- data/lib/kuby/docker/yarn_phase.rb +29 -5
- data/lib/kuby/docker.rb +2 -1
- data/lib/kuby/kubernetes/bare_metal_provider.rb +12 -10
- data/lib/kuby/kubernetes/deployer.rb +22 -10
- data/lib/kuby/kubernetes/docker_config.rb +1 -0
- data/lib/kuby/kubernetes/provider.rb +1 -0
- data/lib/kuby/kubernetes/spec.rb +63 -13
- data/lib/kuby/plugin.rb +23 -1
- data/lib/kuby/plugin_registry.rb +15 -0
- data/lib/kuby/plugins/nginx_ingress.rb +8 -6
- data/lib/kuby/plugins/rails_app/assets.rb +16 -4
- data/lib/kuby/plugins/rails_app/assets_image.rb +18 -11
- data/lib/kuby/plugins/rails_app/crdb/plugin.rb +473 -0
- data/lib/kuby/plugins/rails_app/crdb.rb +9 -0
- data/lib/kuby/plugins/rails_app/database.rb +12 -8
- data/lib/kuby/plugins/rails_app/generators/kuby.rb +17 -16
- data/lib/kuby/plugins/rails_app/plugin.rb +37 -27
- data/lib/kuby/plugins/rails_app/sqlite.rb +7 -3
- data/lib/kuby/plugins/rails_app/tasks.rake +25 -12
- data/lib/kuby/plugins/rails_app.rb +1 -0
- data/lib/kuby/plugins/system.rb +16 -0
- data/lib/kuby/plugins.rb +1 -0
- data/lib/kuby/railtie.rb +31 -1
- data/lib/kuby/tasks.rb +91 -10
- data/lib/kuby/trailing_hash.rb +2 -2
- data/lib/kuby/utils/sem_ver/constraint.rb +68 -0
- data/lib/kuby/utils/sem_ver/constraint_set.rb +25 -0
- data/lib/kuby/utils/sem_ver/version.rb +49 -0
- data/lib/kuby/utils/sem_ver.rb +17 -0
- data/lib/kuby/utils/table.rb +35 -0
- data/lib/kuby/utils/which.rb +65 -0
- data/lib/kuby/utils.rb +11 -0
- data/lib/kuby/version.rb +1 -1
- data/lib/kuby.rb +37 -2
- data/rbi/kuby-core.rbi +2128 -0
- data/spec/docker/spec_spec.rb +50 -26
- data/spec/docker/timestamped_image_spec.rb +2 -2
- data/spec/dummy/app/channels/application_cable/channel.rb +2 -1
- data/spec/dummy/app/channels/application_cable/connection.rb +2 -1
- data/spec/dummy/app/controllers/application_controller.rb +2 -1
- data/spec/dummy/app/jobs/application_job.rb +2 -1
- data/spec/dummy/app/mailers/application_mailer.rb +2 -1
- data/spec/dummy/app/models/application_record.rb +2 -1
- data/spec/dummy/config/application.rb +2 -1
- data/spec/dummy/config/initializers/wrap_parameters.rb +2 -1
- data/spec/dummy/config/routes.rb +2 -1
- data/spec/dummy/test/application_system_test_case.rb +2 -1
- data/spec/dummy/test/channels/application_cable/connection_test.rb +2 -1
- data/spec/spec_helper.rb +13 -1
- metadata +46 -39
- data/lib/kuby/plugins/rails_app/mysql.rb +0 -158
- data/lib/kuby/plugins/rails_app/postgres.rb +0 -163
data/lib/kuby/docker/cli.rb
CHANGED
@@ -7,29 +7,29 @@ require 'shellwords'
|
|
7
7
|
module Kuby
|
8
8
|
module Docker
|
9
9
|
class CLI < CLIBase
|
10
|
-
extend T::Sig
|
10
|
+
# extend T::Sig
|
11
11
|
|
12
|
-
sig { returns(String) }
|
12
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
13
13
|
attr_reader :executable
|
14
14
|
|
15
|
-
sig { params(executable: T.nilable(String)).void }
|
15
|
+
# T::Sig::WithoutRuntime.sig { params(executable: T.nilable(String)).void }
|
16
16
|
def initialize(executable = nil)
|
17
|
-
@executable =
|
17
|
+
@executable = executable || Kuby::Utils.which('docker')
|
18
18
|
end
|
19
19
|
|
20
|
-
sig { returns(T.nilable(String)) }
|
20
|
+
# T::Sig::WithoutRuntime.sig { returns(T.nilable(String)) }
|
21
21
|
def config_file
|
22
22
|
if File.exist?(default_config_file)
|
23
23
|
default_config_file
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
sig { returns(String) }
|
27
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
28
28
|
def default_config_file
|
29
29
|
File.join(Dir.home, '.docker', 'config.json')
|
30
30
|
end
|
31
31
|
|
32
|
-
sig { params(url: String, username: String, password: String).void }
|
32
|
+
# T::Sig::WithoutRuntime.sig { params(url: String, username: String, password: String).void }
|
33
33
|
def login(url:, username:, password:)
|
34
34
|
cmd = [
|
35
35
|
executable, 'login', url, '--username', username, '--password-stdin'
|
@@ -39,52 +39,67 @@ module Kuby
|
|
39
39
|
stdin.puts(password)
|
40
40
|
end
|
41
41
|
|
42
|
-
unless
|
42
|
+
unless last_status.success?
|
43
43
|
raise LoginError, 'build failed: docker command exited with '\
|
44
|
-
"status code #{
|
44
|
+
"status code #{last_status.exitstatus}"
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
sig { returns(T::Array[String]) }
|
48
|
+
# T::Sig::WithoutRuntime.sig { returns(T::Array[String]) }
|
49
49
|
def auths
|
50
50
|
return [] unless config_file
|
51
51
|
|
52
|
-
config = JSON.parse(File.read(
|
52
|
+
config = JSON.parse(File.read(config_file))
|
53
53
|
config.fetch('auths', {}).keys
|
54
54
|
end
|
55
55
|
|
56
|
-
|
57
|
-
|
56
|
+
# T::Sig::WithoutRuntime.sig {
|
57
|
+
# params(
|
58
|
+
# image: Image,
|
59
|
+
# build_args: T::Hash[T.any(Symbol, String), String],
|
60
|
+
# docker_args: T::Array[String],
|
61
|
+
# context: T.nilable(String),
|
62
|
+
# cache_from: T.nilable(String)
|
63
|
+
# ).void
|
64
|
+
# }
|
65
|
+
def build(image, build_args: {}, docker_args: [], context: nil, cache_from: nil)
|
58
66
|
cmd = [
|
59
67
|
executable, 'build',
|
60
68
|
*image.tags.flat_map { |tag| ['-t', "#{image.image_url}:#{tag}"] },
|
61
69
|
*build_args.flat_map do |arg, val|
|
62
70
|
['--build-arg', Shellwords.shellescape("#{arg}=#{val}")]
|
63
|
-
end
|
71
|
+
end
|
72
|
+
]
|
73
|
+
|
74
|
+
if cache_from
|
75
|
+
cmd += ['--cache-from', cache_from]
|
76
|
+
end
|
77
|
+
|
78
|
+
cmd += [
|
64
79
|
'-f-',
|
65
80
|
*docker_args,
|
66
|
-
'.'
|
81
|
+
context || '.'
|
67
82
|
]
|
68
83
|
|
69
84
|
open3_w(cmd) do |stdin, _wait_threads|
|
70
85
|
stdin.puts(image.dockerfile.to_s)
|
71
86
|
end
|
72
87
|
|
73
|
-
unless
|
88
|
+
unless last_status.success?
|
74
89
|
raise BuildError, 'build failed: docker command exited with '\
|
75
|
-
"status code #{
|
90
|
+
"status code #{last_status.exitstatus}"
|
76
91
|
end
|
77
92
|
end
|
78
93
|
|
79
|
-
sig {
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
}
|
94
|
+
# T::Sig::WithoutRuntime.sig {
|
95
|
+
# params(
|
96
|
+
# image_url: String,
|
97
|
+
# tag: String,
|
98
|
+
# env: T::Hash[T.any(Symbol, String), String],
|
99
|
+
# ports: T::Array[T.any(String, Integer)]
|
100
|
+
# )
|
101
|
+
# .void
|
102
|
+
# }
|
88
103
|
def run(image_url:, tag: 'latest', env: {}, ports: [])
|
89
104
|
cmd = [
|
90
105
|
executable, 'run',
|
@@ -98,13 +113,33 @@ module Kuby
|
|
98
113
|
execc(cmd)
|
99
114
|
end
|
100
115
|
|
101
|
-
sig { params(
|
102
|
-
def
|
116
|
+
# T::Sig::WithoutRuntime.sig { params(container: String, command: String, tty: T::Boolean).returns(String) }
|
117
|
+
def exec_capture(container:, command:, tty: true)
|
118
|
+
cmd = [executable, 'exec']
|
119
|
+
cmd << '-it' if tty
|
120
|
+
cmd += [container, command]
|
121
|
+
|
122
|
+
backticks(cmd)
|
123
|
+
end
|
124
|
+
|
125
|
+
# T::Sig::WithoutRuntime.sig { params(image_url: String, tag: String, format: T.nilable(String)).returns(String) }
|
126
|
+
def inspect(image_url:, tag: 'latest', format: nil)
|
127
|
+
cmd = [executable, 'inspect']
|
128
|
+
cmd += ['--format', "'#{format}'"]
|
129
|
+
cmd << "#{image_url}:#{tag}"
|
130
|
+
|
131
|
+
backticks(cmd)
|
132
|
+
end
|
133
|
+
|
134
|
+
# T::Sig::WithoutRuntime.sig { params(image_url: String, digests: T::Boolean).returns(T::Array[T::Hash[Symbol, String]]) }
|
135
|
+
def images(image_url, digests: true)
|
103
136
|
cmd = [
|
104
137
|
executable, 'images', image_url,
|
105
138
|
'--format', '"{{json . }}"'
|
106
139
|
]
|
107
140
|
|
141
|
+
cmd << '--digests' if digests
|
142
|
+
|
108
143
|
backticks(cmd).split("\n").map do |image_data|
|
109
144
|
JSON.parse(image_data).each_with_object({}) do |(k, v), ret|
|
110
145
|
ret[k.underscore.to_sym] = v
|
@@ -112,41 +147,41 @@ module Kuby
|
|
112
147
|
end
|
113
148
|
end
|
114
149
|
|
115
|
-
sig { params(image_url: String, tag: String).void }
|
150
|
+
# T::Sig::WithoutRuntime.sig { params(image_url: String, tag: String).void }
|
116
151
|
def push(image_url, tag)
|
117
152
|
systemm([
|
118
153
|
executable, 'push', "#{image_url}:#{tag}"
|
119
154
|
])
|
120
155
|
|
121
|
-
unless
|
156
|
+
unless last_status.success?
|
122
157
|
raise PushError, 'push failed: docker command exited with '\
|
123
|
-
"status code #{
|
158
|
+
"status code #{last_status.exitstatus}"
|
124
159
|
end
|
125
160
|
end
|
126
161
|
|
127
|
-
sig { params(image_url: String, tag: String).void }
|
162
|
+
# T::Sig::WithoutRuntime.sig { params(image_url: String, tag: String).void }
|
128
163
|
def pull(image_url, tag)
|
129
164
|
systemm([
|
130
165
|
executable, 'pull', "#{image_url}:#{tag}"
|
131
166
|
])
|
132
167
|
|
133
|
-
unless
|
168
|
+
unless last_status.success?
|
134
169
|
raise PullError, 'pull failed: docker command exited with '\
|
135
|
-
"status code #{
|
170
|
+
"status code #{last_status.exitstatus}"
|
136
171
|
end
|
137
172
|
end
|
138
173
|
|
139
|
-
sig { returns(Symbol) }
|
174
|
+
# T::Sig::WithoutRuntime.sig { returns(Symbol) }
|
140
175
|
def status_key
|
141
176
|
:kuby_docker_cli_last_status
|
142
177
|
end
|
143
178
|
|
144
|
-
sig { returns(Symbol) }
|
179
|
+
# T::Sig::WithoutRuntime.sig { returns(Symbol) }
|
145
180
|
def stdout_key
|
146
181
|
:kuby_docker_stdout
|
147
182
|
end
|
148
183
|
|
149
|
-
sig { returns(Symbol) }
|
184
|
+
# T::Sig::WithoutRuntime.sig { returns(Symbol) }
|
150
185
|
def stderr_key
|
151
186
|
:kuby_docker_stderr
|
152
187
|
end
|
@@ -3,25 +3,25 @@
|
|
3
3
|
module Kuby
|
4
4
|
module Docker
|
5
5
|
class CopyPhase < Layer
|
6
|
-
extend T::Sig
|
6
|
+
# extend T::Sig
|
7
7
|
|
8
|
-
DEFAULT_PATHS =
|
8
|
+
DEFAULT_PATHS = ['./'].freeze
|
9
9
|
|
10
|
-
sig { returns(T::Array[String]) }
|
10
|
+
# T::Sig::WithoutRuntime.sig { returns(T::Array[String]) }
|
11
11
|
attr_reader :paths
|
12
12
|
|
13
|
-
sig { params(environment: Environment).void }
|
13
|
+
# T::Sig::WithoutRuntime.sig { params(environment: Environment).void }
|
14
14
|
def initialize(environment)
|
15
15
|
super
|
16
|
-
@paths =
|
16
|
+
@paths = []
|
17
17
|
end
|
18
18
|
|
19
|
-
sig { params(path: String).void }
|
19
|
+
# T::Sig::WithoutRuntime.sig { params(path: String).void }
|
20
20
|
def <<(path)
|
21
21
|
paths << path
|
22
22
|
end
|
23
23
|
|
24
|
-
sig { params(dockerfile: Dockerfile).void }
|
24
|
+
# T::Sig::WithoutRuntime.sig { params(dockerfile: Dockerfile).void }
|
25
25
|
def apply_to(dockerfile)
|
26
26
|
to_copy = paths.empty? ? DEFAULT_PATHS : paths
|
27
27
|
to_copy.each { |path| dockerfile.copy(path, '.') }
|
data/lib/kuby/docker/debian.rb
CHANGED
@@ -3,39 +3,39 @@
|
|
3
3
|
module Kuby
|
4
4
|
module Docker
|
5
5
|
class Debian < Distro
|
6
|
-
SHELL_EXE =
|
6
|
+
SHELL_EXE = '/bin/bash'.freeze
|
7
7
|
|
8
|
-
DEFAULT_PACKAGES =
|
8
|
+
DEFAULT_PACKAGES = [
|
9
9
|
[:ca_certificates, nil],
|
10
10
|
[:nodejs, '12.14.1'],
|
11
11
|
[:yarn, '1.21.1']
|
12
|
-
].freeze
|
12
|
+
].freeze
|
13
13
|
|
14
|
-
sig { returns(Layer) }
|
14
|
+
# T::Sig::WithoutRuntime.sig { returns(Layer) }
|
15
15
|
attr_reader :phase
|
16
16
|
|
17
|
-
sig { override.params(packages: T::Array[Distro::PackageImpl], into: Dockerfile).void }
|
17
|
+
# T::Sig::WithoutRuntime.sig { override.params(packages: T::Array[Distro::PackageImpl], into: Dockerfile).void }
|
18
18
|
def install(packages, into:)
|
19
19
|
dockerfile = into
|
20
20
|
install_managed(packages, dockerfile)
|
21
21
|
install_unmanaged(packages, dockerfile)
|
22
22
|
end
|
23
23
|
|
24
|
-
sig { override.returns(T::Array[[Symbol, T.nilable(String)]]) }
|
24
|
+
# T::Sig::WithoutRuntime.sig { override.returns(T::Array[[Symbol, T.nilable(String)]]) }
|
25
25
|
def default_packages
|
26
26
|
DEFAULT_PACKAGES
|
27
27
|
end
|
28
28
|
|
29
|
-
sig { override.returns(String) }
|
29
|
+
# T::Sig::WithoutRuntime.sig { override.returns(String) }
|
30
30
|
def shell_exe
|
31
31
|
SHELL_EXE
|
32
32
|
end
|
33
33
|
|
34
34
|
private
|
35
35
|
|
36
|
-
sig { params(packages: T::Array[Distro::PackageImpl], dockerfile: Dockerfile).void }
|
36
|
+
# T::Sig::WithoutRuntime.sig { params(packages: T::Array[Distro::PackageImpl], dockerfile: Dockerfile).void }
|
37
37
|
def install_managed(packages, dockerfile)
|
38
|
-
pkgs =
|
38
|
+
pkgs = packages.select(&:managed?)
|
39
39
|
|
40
40
|
pkg_cmd = <<~CMD.strip
|
41
41
|
apt-get update -qq && \\
|
@@ -52,7 +52,7 @@ module Kuby
|
|
52
52
|
dockerfile.run(pkg_cmd)
|
53
53
|
end
|
54
54
|
|
55
|
-
sig { params(packages: T::Array[Distro::PackageImpl], dockerfile: Dockerfile).void }
|
55
|
+
# T::Sig::WithoutRuntime.sig { params(packages: T::Array[Distro::PackageImpl], dockerfile: Dockerfile).void }
|
56
56
|
def install_unmanaged(packages, dockerfile)
|
57
57
|
packages
|
58
58
|
.reject(&:managed?)
|
data/lib/kuby/docker/distro.rb
CHANGED
@@ -3,37 +3,37 @@
|
|
3
3
|
module Kuby
|
4
4
|
module Docker
|
5
5
|
class Distro
|
6
|
-
extend T::Sig
|
7
|
-
extend T::Helpers
|
6
|
+
# extend T::Sig
|
7
|
+
# extend T::Helpers
|
8
8
|
|
9
|
-
abstract!
|
9
|
+
# abstract!
|
10
10
|
|
11
|
-
PackageImpl = T.type_alias {
|
12
|
-
|
13
|
-
}
|
11
|
+
# PackageImpl = T.type_alias {
|
12
|
+
# T.any(Packages::Package, Packages::ManagedPackage, Packages::SimpleManagedPackage)
|
13
|
+
# }
|
14
14
|
|
15
|
-
ManagedPackageImpl = T.type_alias {
|
16
|
-
|
17
|
-
}
|
15
|
+
# ManagedPackageImpl = T.type_alias {
|
16
|
+
# T.any(Packages::ManagedPackage, Packages::SimpleManagedPackage)
|
17
|
+
# }
|
18
18
|
|
19
|
-
sig { params(phase: Layer).void }
|
19
|
+
# T::Sig::WithoutRuntime.sig { params(phase: Layer).void }
|
20
20
|
def initialize(phase)
|
21
21
|
@phase = phase
|
22
22
|
end
|
23
23
|
|
24
|
-
sig { params(packages: T::Array[PackageImpl], into: Dockerfile).void }
|
24
|
+
# T::Sig::WithoutRuntime.sig { params(packages: T::Array[PackageImpl], into: Dockerfile).void }
|
25
25
|
def install(packages, into:)
|
26
26
|
raise NotImplementedError,
|
27
27
|
"#{__method__} must be defined in derived classes"
|
28
28
|
end
|
29
29
|
|
30
|
-
sig { returns(T::Array[[Symbol, T.nilable(String)]]) }
|
30
|
+
# T::Sig::WithoutRuntime.sig { returns(T::Array[[Symbol, T.nilable(String)]]) }
|
31
31
|
def default_packages
|
32
32
|
raise NotImplementedError,
|
33
33
|
"#{__method__} must be defined in derived classes"
|
34
34
|
end
|
35
35
|
|
36
|
-
sig { returns(String) }
|
36
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
37
37
|
def shell_exe
|
38
38
|
raise NotImplementedError,
|
39
39
|
"#{__method__} must be defined in derived classes"
|
@@ -3,13 +3,13 @@
|
|
3
3
|
module Kuby
|
4
4
|
module Docker
|
5
5
|
class DockerURI
|
6
|
-
extend T::Sig
|
6
|
+
# extend T::Sig
|
7
7
|
|
8
|
-
DEFAULT_REGISTRY_HOST =
|
9
|
-
DEFAULT_REGISTRY_INDEX_HOST =
|
10
|
-
DEFAULT_PORT =
|
8
|
+
DEFAULT_REGISTRY_HOST = 'docker.io'.freeze
|
9
|
+
DEFAULT_REGISTRY_INDEX_HOST = 'index.docker.io'.freeze
|
10
|
+
DEFAULT_PORT = 443
|
11
11
|
|
12
|
-
sig { params(url: String).returns(DockerURI) }
|
12
|
+
# T::Sig::WithoutRuntime.sig { params(url: String).returns(DockerURI) }
|
13
13
|
def self.parse_uri(url)
|
14
14
|
parse(
|
15
15
|
url,
|
@@ -18,7 +18,7 @@ module Kuby
|
|
18
18
|
)
|
19
19
|
end
|
20
20
|
|
21
|
-
sig { params(url: String).returns(DockerURI) }
|
21
|
+
# T::Sig::WithoutRuntime.sig { params(url: String).returns(DockerURI) }
|
22
22
|
def self.parse_index_uri(url)
|
23
23
|
parse(
|
24
24
|
url,
|
@@ -27,13 +27,13 @@ module Kuby
|
|
27
27
|
)
|
28
28
|
end
|
29
29
|
|
30
|
-
sig {
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
}
|
30
|
+
# T::Sig::WithoutRuntime.sig {
|
31
|
+
# params(
|
32
|
+
# url: String,
|
33
|
+
# default_host: T.nilable(String),
|
34
|
+
# default_port: T.nilable(Integer)
|
35
|
+
# ).returns(DockerURI)
|
36
|
+
# }
|
37
37
|
def self.parse(url, default_host:, default_port:)
|
38
38
|
if idx = url.index('://')
|
39
39
|
url = url[(idx + 3)..-1] || ''
|
@@ -41,8 +41,8 @@ module Kuby
|
|
41
41
|
|
42
42
|
host_port, *path = url.split('/')
|
43
43
|
host, port, *path = if host_port =~ /[.:]/
|
44
|
-
hst, prt =
|
45
|
-
[
|
44
|
+
hst, prt = host_port.split(':')
|
45
|
+
[hst, prt || default_port, *path]
|
46
46
|
else
|
47
47
|
[default_host, default_port, host_port, *path]
|
48
48
|
end
|
@@ -50,23 +50,23 @@ module Kuby
|
|
50
50
|
new(host.to_s, port.to_i, (path || []).join('/'))
|
51
51
|
end
|
52
52
|
|
53
|
-
sig { returns(String) }
|
53
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
54
54
|
attr_reader :host
|
55
55
|
|
56
|
-
sig { returns(Integer) }
|
56
|
+
# T::Sig::WithoutRuntime.sig { returns(Integer) }
|
57
57
|
attr_reader :port
|
58
58
|
|
59
|
-
sig { returns(String) }
|
59
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
60
60
|
attr_reader :path
|
61
61
|
|
62
|
-
sig { params(host: String, port: Integer, path: String).void }
|
62
|
+
# T::Sig::WithoutRuntime.sig { params(host: String, port: Integer, path: String).void }
|
63
63
|
def initialize(host, port, path)
|
64
64
|
@host = host
|
65
65
|
@port = port
|
66
66
|
@path = path
|
67
67
|
end
|
68
68
|
|
69
|
-
sig { returns(T::Boolean) }
|
69
|
+
# T::Sig::WithoutRuntime.sig { returns(T::Boolean) }
|
70
70
|
def has_default_port?
|
71
71
|
port == DEFAULT_PORT
|
72
72
|
end
|
@@ -5,39 +5,39 @@ require 'digest'
|
|
5
5
|
module Kuby
|
6
6
|
module Docker
|
7
7
|
class Dockerfile
|
8
|
-
extend T::Sig
|
8
|
+
# extend T::Sig
|
9
9
|
|
10
10
|
class Command
|
11
|
-
extend T::Sig
|
11
|
+
# extend T::Sig
|
12
12
|
|
13
|
-
sig { returns(T::Array[T.any(String, Integer)]) }
|
13
|
+
# T::Sig::WithoutRuntime.sig { returns(T::Array[T.any(String, Integer)]) }
|
14
14
|
attr_reader :args
|
15
15
|
|
16
|
-
sig { params(args: T::Array[T.any(String, Integer)]).void }
|
16
|
+
# T::Sig::WithoutRuntime.sig { params(args: T::Array[T.any(String, Integer)]).void }
|
17
17
|
def initialize(args)
|
18
18
|
@args = args
|
19
19
|
end
|
20
20
|
|
21
|
-
sig { returns(String) }
|
21
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
22
22
|
def to_s
|
23
23
|
args.join(' ')
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
class From < Command
|
28
|
-
sig { returns(String) }
|
28
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
29
29
|
attr_reader :image_url
|
30
30
|
|
31
|
-
sig { returns(T.nilable(String)) }
|
31
|
+
# T::Sig::WithoutRuntime.sig { returns(T.nilable(String)) }
|
32
32
|
attr_reader :as
|
33
33
|
|
34
|
-
sig { params(image_url: String, as: T.nilable(String)).void }
|
34
|
+
# T::Sig::WithoutRuntime.sig { params(image_url: String, as: T.nilable(String)).void }
|
35
35
|
def initialize(image_url, as: nil)
|
36
36
|
@image_url = image_url
|
37
37
|
@as = as
|
38
38
|
end
|
39
39
|
|
40
|
-
sig { returns(String) }
|
40
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
41
41
|
def to_s
|
42
42
|
str = "FROM #{image_url}"
|
43
43
|
str << " AS #{as}" if as
|
@@ -46,38 +46,38 @@ module Kuby
|
|
46
46
|
end
|
47
47
|
|
48
48
|
class Workdir < Command
|
49
|
-
sig { returns(String) }
|
49
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
50
50
|
def to_s; "WORKDIR #{super}"; end
|
51
51
|
end
|
52
52
|
|
53
53
|
class Env < Command
|
54
|
-
sig { returns(String) }
|
54
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
55
55
|
def to_s; "ENV #{super}"; end
|
56
56
|
end
|
57
57
|
|
58
58
|
class Run < Command
|
59
|
-
sig { returns(String) }
|
59
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
60
60
|
def to_s; "RUN #{super}"; end
|
61
61
|
end
|
62
62
|
|
63
63
|
class Copy < Command
|
64
|
-
sig { returns(String) }
|
64
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
65
65
|
attr_reader :source
|
66
66
|
|
67
|
-
sig { returns(String) }
|
67
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
68
68
|
attr_reader :dest
|
69
69
|
|
70
|
-
sig { returns(T.nilable(String)) }
|
70
|
+
# T::Sig::WithoutRuntime.sig { returns(T.nilable(String)) }
|
71
71
|
attr_reader :from
|
72
72
|
|
73
|
-
sig { params(source: String, dest: String, from: T.nilable(String)).void }
|
73
|
+
# T::Sig::WithoutRuntime.sig { params(source: String, dest: String, from: T.nilable(String)).void }
|
74
74
|
def initialize(source, dest, from: nil)
|
75
75
|
@source = source
|
76
76
|
@dest = dest
|
77
77
|
@from = from
|
78
78
|
end
|
79
79
|
|
80
|
-
sig { returns(String) }
|
80
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
81
81
|
def to_s
|
82
82
|
cmd = ['COPY']
|
83
83
|
cmd << "--from=#{from}" if from
|
@@ -87,91 +87,100 @@ module Kuby
|
|
87
87
|
end
|
88
88
|
|
89
89
|
class Expose < Command
|
90
|
-
sig { returns(String) }
|
90
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
91
91
|
def to_s; "EXPOSE #{super}"; end
|
92
92
|
end
|
93
93
|
|
94
94
|
class Cmd < Command
|
95
|
-
sig { returns(String) }
|
95
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
96
96
|
def to_s; "CMD #{super}"; end
|
97
97
|
end
|
98
98
|
|
99
99
|
class Arg < Command
|
100
|
-
sig { returns(String) }
|
100
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
101
101
|
def to_s; "ARG #{super}"; end
|
102
102
|
end
|
103
103
|
|
104
|
-
sig { returns(T::Array[Command]) }
|
104
|
+
# T::Sig::WithoutRuntime.sig { returns(T::Array[Command]) }
|
105
105
|
attr_reader :commands
|
106
106
|
|
107
|
-
sig { returns(Integer) }
|
107
|
+
# T::Sig::WithoutRuntime.sig { returns(Integer) }
|
108
108
|
attr_reader :cursor
|
109
109
|
|
110
|
-
sig { void }
|
110
|
+
# T::Sig::WithoutRuntime.sig { void }
|
111
111
|
def initialize
|
112
|
-
@commands =
|
113
|
-
@cursor =
|
112
|
+
@commands = []
|
113
|
+
@cursor = 0
|
114
114
|
end
|
115
115
|
|
116
|
-
sig { params(image_url: String, as: T.nilable(String)).void }
|
116
|
+
# T::Sig::WithoutRuntime.sig { params(image_url: String, as: T.nilable(String)).void }
|
117
117
|
def from(image_url, as: nil)
|
118
118
|
add From.new(image_url, as: as)
|
119
119
|
end
|
120
120
|
|
121
|
-
sig { params(args: String).void }
|
121
|
+
# T::Sig::WithoutRuntime.sig { params(args: String).void }
|
122
122
|
def workdir(*args)
|
123
123
|
add Workdir.new(args)
|
124
124
|
end
|
125
125
|
|
126
|
-
sig { params(args: String).void }
|
126
|
+
# T::Sig::WithoutRuntime.sig { params(args: String).void }
|
127
127
|
def env(*args)
|
128
128
|
add Env.new(args)
|
129
129
|
end
|
130
130
|
|
131
|
-
sig { params(args: String).void }
|
131
|
+
# T::Sig::WithoutRuntime.sig { params(args: String).void }
|
132
132
|
def arg(*args)
|
133
133
|
add Arg.new(args)
|
134
134
|
end
|
135
135
|
|
136
|
-
sig { params(args: String).void }
|
136
|
+
# T::Sig::WithoutRuntime.sig { params(args: String).void }
|
137
137
|
def run(*args)
|
138
138
|
add Run.new(args)
|
139
139
|
end
|
140
140
|
|
141
|
-
sig { params(source: String, dest: String, from: T.nilable(String)).void }
|
141
|
+
# T::Sig::WithoutRuntime.sig { params(source: String, dest: String, from: T.nilable(String)).void }
|
142
142
|
def copy(source, dest, from: nil)
|
143
143
|
add Copy.new(source, dest, from: from)
|
144
144
|
end
|
145
145
|
|
146
|
-
sig { params(port: Integer).void }
|
146
|
+
# T::Sig::WithoutRuntime.sig { params(port: Integer).void }
|
147
147
|
def expose(port)
|
148
148
|
add Expose.new([port])
|
149
149
|
end
|
150
150
|
|
151
|
-
sig { params(args: String).void }
|
151
|
+
# T::Sig::WithoutRuntime.sig { params(args: String).void }
|
152
152
|
def cmd(*args)
|
153
153
|
add Cmd.new(args)
|
154
154
|
end
|
155
155
|
|
156
|
-
sig { returns(String) }
|
156
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
157
157
|
def to_s
|
158
158
|
# ensure trailing newline
|
159
159
|
"#{commands.map(&:to_s).join("\n")}\n"
|
160
160
|
end
|
161
161
|
|
162
|
-
sig { returns(String) }
|
162
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
163
163
|
def checksum
|
164
164
|
Digest::SHA256.hexdigest(to_s)
|
165
165
|
end
|
166
166
|
|
167
|
-
sig { returns(T::Array[Integer]) }
|
167
|
+
# T::Sig::WithoutRuntime.sig { returns(T::Array[Integer]) }
|
168
168
|
def exposed_ports
|
169
169
|
commands
|
170
170
|
.select { |c| c.is_a?(Expose) }
|
171
|
-
.map { |c|
|
171
|
+
.map { |c| c.args.first }
|
172
172
|
end
|
173
173
|
|
174
|
-
sig {
|
174
|
+
# T::Sig::WithoutRuntime.sig { returns(T.nilable(String)) }
|
175
|
+
def current_workdir
|
176
|
+
found = commands.reverse_each.find do |command|
|
177
|
+
command.is_a?(Kuby::Docker::Dockerfile::Workdir)
|
178
|
+
end
|
179
|
+
|
180
|
+
found.args.first if found
|
181
|
+
end
|
182
|
+
|
183
|
+
# T::Sig::WithoutRuntime.sig { params(pos: Integer, block: T.proc.void).void }
|
175
184
|
def insert_at(pos, &block)
|
176
185
|
@cursor = pos
|
177
186
|
yield
|
@@ -181,7 +190,7 @@ module Kuby
|
|
181
190
|
|
182
191
|
private
|
183
192
|
|
184
|
-
sig { params(cmd: Command).void }
|
193
|
+
# T::Sig::WithoutRuntime.sig { params(cmd: Command).void }
|
185
194
|
def add(cmd)
|
186
195
|
commands.insert(cursor, cmd)
|
187
196
|
@cursor += 1
|