kuby-core 0.11.0 → 0.11.6
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/lib/kuby.rb +4 -2
- data/lib/kuby/basic_logger.rb +56 -8
- data/lib/kuby/cli_base.rb +51 -12
- data/lib/kuby/commands.rb +10 -1
- data/lib/kuby/definition.rb +15 -2
- data/lib/kuby/dev_setup.rb +113 -23
- data/lib/kuby/docker/cli.rb +10 -10
- data/lib/kuby/docker/dev_spec.rb +12 -5
- data/lib/kuby/docker/dockerfile.rb +7 -7
- data/lib/kuby/docker/spec.rb +1 -1
- data/lib/kuby/docker/webserver_phase.rb +5 -5
- data/lib/kuby/kubernetes/spec.rb +18 -3
- data/lib/kuby/plugins/rails_app/generators/kuby.rb +19 -1
- data/lib/kuby/plugins/rails_app/mysql.rb +5 -0
- data/lib/kuby/plugins/rails_app/plugin.rb +0 -1
- data/lib/kuby/plugins/rails_app/postgres.rb +5 -0
- data/lib/kuby/plugins/rails_app/sqlite.rb +13 -0
- data/lib/kuby/version.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 231bc8c37af35418336ba5bb5853049e0d9192932a65eeb3e81a0471b5761953
|
4
|
+
data.tar.gz: 9a4e4426e1d183505f09fac2761601c101c92423761647484c1dae3c3a75e235
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64bd169c3454d196efcf0a21f400107ca8b8c584a20793a8ccf232767aba7ae52fab27307f01e104186b73f537d12907afc86c901538f86266773dacb740cbaa
|
7
|
+
data.tar.gz: a54f9fa2eb0cdbfe52a0d4799c1f4fa9bd4677bef8ef4ed4f11caa4690d28f077918a0feb76926b94923ee6ba00e5065d8edabb1997d829d4f7ff5f9b9832708
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
## 0.11.6
|
2
|
+
* Fix Rails generator.
|
3
|
+
- Causing `undefined method 'module_parent_name'`. Apparently `module_parent_name` wasn't introduced until Rails 6.
|
4
|
+
|
5
|
+
## 0.11.5
|
6
|
+
* Raise friendlier error when attempting to add Docker credentials in the development environment.
|
7
|
+
* Raise friendlier error when attempting to set a username and password for SQLite databases.
|
8
|
+
|
9
|
+
## 0.11.4
|
10
|
+
* Fix bug causing crash when running CLI commands.
|
11
|
+
- Turns out was caused by adding a Sorbet type annotation inside an anonymous singleton class and forgetting to extend `T::Sig`. Thanks @lazyatom!
|
12
|
+
|
13
|
+
## 0.11.3
|
14
|
+
* I've gone back and forth a few times on this, but I decided to put the initializer code back into the Rails generator.
|
15
|
+
|
16
|
+
## 0.11.2
|
17
|
+
* Attempt to auto-require the requested provider if it isn't registered.
|
18
|
+
* Adjust error message when provider can't be found to include reminder to add a require statement.
|
19
|
+
|
20
|
+
## 0.11.1
|
21
|
+
* Use integers for ports instead of strings to appease Kubernetes.
|
22
|
+
|
1
23
|
## 0.11.0
|
2
24
|
* Defer evaluation of database config until after Kuby has been configured.
|
3
25
|
- The issue that prompted this was that the `database` block was being evaluated before the Rails root had been set via `root`. Kuby couldn't find database.yml in a non-standard location and blew up with an error.
|
data/lib/kuby.rb
CHANGED
@@ -59,8 +59,10 @@ module Kuby
|
|
59
59
|
tls_enabled false
|
60
60
|
|
61
61
|
database do
|
62
|
-
|
63
|
-
|
62
|
+
if requires_credentials?
|
63
|
+
user(DEFAULT_DB_USER)
|
64
|
+
password(DEFAULT_DB_PASSWORD)
|
65
|
+
end
|
64
66
|
end
|
65
67
|
end
|
66
68
|
|
data/lib/kuby/basic_logger.rb
CHANGED
@@ -1,10 +1,30 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
|
+
|
2
3
|
require 'logger'
|
3
4
|
require 'colorized_string'
|
4
5
|
|
5
6
|
module Kuby
|
6
7
|
class BasicLogger < Logger
|
7
|
-
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig {
|
11
|
+
override.params(
|
12
|
+
logdev: T.any(String, IO, StringIO, NilClass),
|
13
|
+
shift_age: Integer,
|
14
|
+
shift_size: Integer,
|
15
|
+
level: Integer,
|
16
|
+
progname: T.nilable(String),
|
17
|
+
formatter: T.nilable(FormatterProcType),
|
18
|
+
datetime_format: T.nilable(String),
|
19
|
+
shift_period_suffix: T.nilable(String)
|
20
|
+
).void
|
21
|
+
}
|
22
|
+
def initialize(
|
23
|
+
logdev, shift_age = 0, shift_size = 1048576, level: DEBUG,
|
24
|
+
progname: nil, formatter: nil, datetime_format: nil,
|
25
|
+
shift_period_suffix: '%Y%m%d')
|
26
|
+
@logdev = T.let(@logdev, T.nilable(Logger::LogDevice))
|
27
|
+
|
8
28
|
super
|
9
29
|
|
10
30
|
self.formatter = proc do |_severity, _datetime, _progname, msg|
|
@@ -12,23 +32,51 @@ module Kuby
|
|
12
32
|
end
|
13
33
|
end
|
14
34
|
|
15
|
-
|
16
|
-
|
35
|
+
sig {
|
36
|
+
override.params(
|
37
|
+
progname_or_msg: T.untyped,
|
38
|
+
block: T.nilable(T.proc.returns(T.untyped))
|
39
|
+
).void
|
40
|
+
}
|
41
|
+
def info(progname_or_msg = nil, &block)
|
42
|
+
if block
|
43
|
+
super(progname_or_msg) { ColorizedString[block.call].yellow }
|
44
|
+
else
|
45
|
+
super(ColorizedString[progname_or_msg].yellow)
|
46
|
+
end
|
17
47
|
end
|
18
48
|
|
19
|
-
|
20
|
-
|
49
|
+
sig {
|
50
|
+
override.params(
|
51
|
+
progname_or_msg: T.untyped,
|
52
|
+
block: T.nilable(T.proc.returns(T.untyped))
|
53
|
+
).void
|
54
|
+
}
|
55
|
+
def fatal(progname_or_msg, &block)
|
56
|
+
if block
|
57
|
+
super(progname_or_msg) { ColorizedString[block.call].red }
|
58
|
+
else
|
59
|
+
super(ColorizedString[progname_or_msg].red)
|
60
|
+
end
|
21
61
|
end
|
22
62
|
|
23
63
|
# adhere to the "CLI" interface
|
24
|
-
|
25
|
-
|
64
|
+
sig {
|
65
|
+
params(
|
66
|
+
out: T.any(IO, StringIO),
|
67
|
+
err: T.any(IO, StringIO),
|
68
|
+
block: T.proc.void
|
69
|
+
).void
|
70
|
+
}
|
71
|
+
def with_pipes(out = STDOUT, err = STDERR, &block)
|
72
|
+
previous_logdev = @logdev&.dev || STDERR
|
26
73
|
reopen(err)
|
27
74
|
yield
|
28
75
|
ensure
|
29
76
|
reopen(previous_logdev)
|
30
77
|
end
|
31
78
|
|
79
|
+
sig { returns(T.nilable(Process::Status)) }
|
32
80
|
def last_status
|
33
81
|
nil
|
34
82
|
end
|
data/lib/kuby/cli_base.rb
CHANGED
@@ -1,24 +1,39 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
|
+
|
2
3
|
require 'open3'
|
3
4
|
require 'thread'
|
4
5
|
|
5
6
|
module Kuby
|
6
7
|
class CLIBase
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig { returns(T.nilable(Process::Status)) }
|
7
11
|
def last_status
|
8
12
|
Thread.current[status_key]
|
9
13
|
end
|
10
14
|
|
15
|
+
sig { params(block: T.proc.params(cmd: String).void).void }
|
11
16
|
def before_execute(&block)
|
17
|
+
@before_execute = T.let(@before_execute, T.nilable(T::Array[T.proc.params(cmd: String).void]))
|
12
18
|
@before_execute ||= []
|
13
19
|
@before_execute << block
|
14
20
|
end
|
15
21
|
|
22
|
+
sig { params(block: T.proc.params(cmd: String).void).void }
|
16
23
|
def after_execute(&block)
|
24
|
+
@after_execute = T.let(@after_execute, T.nilable(T::Array[T.proc.params(cmd: String).void]))
|
17
25
|
@after_execute ||= []
|
18
26
|
@after_execute << block
|
19
27
|
end
|
20
28
|
|
21
|
-
|
29
|
+
sig {
|
30
|
+
params(
|
31
|
+
out: T.any(IO, StringIO),
|
32
|
+
err: T.any(IO, StringIO),
|
33
|
+
block: T.proc.void
|
34
|
+
).void
|
35
|
+
}
|
36
|
+
def with_pipes(out = STDOUT, err = STDERR, &block)
|
22
37
|
previous_stdout = self.stdout
|
23
38
|
previous_stderr = self.stderr
|
24
39
|
self.stdout = out
|
@@ -29,29 +44,39 @@ module Kuby
|
|
29
44
|
self.stderr = previous_stderr
|
30
45
|
end
|
31
46
|
|
47
|
+
sig { returns(T.nilable(T.any(IO, StringIO))) }
|
32
48
|
def stdout
|
33
49
|
Thread.current[stdout_key] || STDOUT
|
34
50
|
end
|
35
51
|
|
52
|
+
sig { params(new_stdout: T.nilable(T.any(IO, StringIO))).void }
|
36
53
|
def stdout=(new_stdout)
|
37
54
|
Thread.current[stdout_key] = new_stdout
|
38
55
|
end
|
39
56
|
|
57
|
+
sig { returns(T.nilable(T.any(IO, StringIO))) }
|
40
58
|
def stderr
|
41
59
|
Thread.current[stderr_key] || STDERR
|
42
60
|
end
|
43
61
|
|
62
|
+
sig { params(new_stderr: T.nilable(T.any(IO, StringIO))).void }
|
44
63
|
def stderr=(new_stderr)
|
45
64
|
Thread.current[stderr_key] = new_stderr
|
46
65
|
end
|
47
66
|
|
48
67
|
private
|
49
68
|
|
50
|
-
|
69
|
+
sig {
|
70
|
+
params(
|
71
|
+
cmd: T::Array[String],
|
72
|
+
block: T.proc.params(stdin: IO).void
|
73
|
+
).void
|
74
|
+
}
|
75
|
+
def open3_w(cmd, &block)
|
51
76
|
run_before_callbacks(cmd)
|
52
77
|
cmd_s = cmd.join(' ')
|
53
78
|
|
54
|
-
Open3.popen3(
|
79
|
+
Open3.popen3(cmd_s) do |p_stdin, p_stdout, p_stderr, wait_thread|
|
55
80
|
Thread.new(stdout) do |t_stdout|
|
56
81
|
begin
|
57
82
|
p_stdout.each { |line| t_stdout.puts(line) }
|
@@ -66,21 +91,23 @@ module Kuby
|
|
66
91
|
end
|
67
92
|
end
|
68
93
|
|
69
|
-
yield(p_stdin)
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
94
|
+
yield(p_stdin)
|
95
|
+
|
96
|
+
p_stdin.close
|
97
|
+
self.last_status = T.cast(wait_thread.value, Process::Status)
|
98
|
+
run_after_callbacks(cmd)
|
99
|
+
wait_thread.join
|
75
100
|
end
|
76
101
|
end
|
77
102
|
|
103
|
+
sig { params(cmd: T::Array[String]).void }
|
78
104
|
def execc(cmd)
|
79
105
|
run_before_callbacks(cmd)
|
80
106
|
cmd_s = cmd.join(' ')
|
81
107
|
exec(cmd_s)
|
82
108
|
end
|
83
109
|
|
110
|
+
sig { params(cmd: T::Array[String]).void }
|
84
111
|
def systemm(cmd)
|
85
112
|
if stdout == STDOUT && stderr == STDERR
|
86
113
|
systemm_default(cmd)
|
@@ -89,6 +116,7 @@ module Kuby
|
|
89
116
|
end
|
90
117
|
end
|
91
118
|
|
119
|
+
sig { params(cmd: T::Array[String]).void }
|
92
120
|
def systemm_default(cmd)
|
93
121
|
run_before_callbacks(cmd)
|
94
122
|
cmd_s = cmd.join(' ')
|
@@ -98,6 +126,7 @@ module Kuby
|
|
98
126
|
end
|
99
127
|
end
|
100
128
|
|
129
|
+
sig { params(cmd: T::Array[String]).void }
|
101
130
|
def systemm_open3(cmd)
|
102
131
|
run_before_callbacks(cmd)
|
103
132
|
cmd_s = cmd.join(' ')
|
@@ -118,12 +147,14 @@ module Kuby
|
|
118
147
|
end
|
119
148
|
|
120
149
|
p_stdin.close
|
121
|
-
self.last_status = wait_thread.value
|
150
|
+
self.last_status = T.cast(wait_thread.value, Process::Status)
|
122
151
|
run_after_callbacks(cmd)
|
123
152
|
wait_thread.join
|
124
153
|
end
|
125
154
|
end
|
126
155
|
|
156
|
+
|
157
|
+
sig { params(cmd: T::Array[String]).returns(String) }
|
127
158
|
def backticks(cmd)
|
128
159
|
if stdout == STDOUT && stderr == STDERR
|
129
160
|
backticks_default(cmd)
|
@@ -132,6 +163,7 @@ module Kuby
|
|
132
163
|
end
|
133
164
|
end
|
134
165
|
|
166
|
+
sig { params(cmd: T::Array[String]).returns(String) }
|
135
167
|
def backticks_default(cmd)
|
136
168
|
run_before_callbacks(cmd)
|
137
169
|
cmd_s = cmd.join(' ')
|
@@ -141,6 +173,7 @@ module Kuby
|
|
141
173
|
end
|
142
174
|
end
|
143
175
|
|
176
|
+
sig { params(cmd: T::Array[String]).returns(String) }
|
144
177
|
def backticks_open3(cmd)
|
145
178
|
run_before_callbacks(cmd)
|
146
179
|
cmd_s = cmd.join(' ')
|
@@ -162,7 +195,7 @@ module Kuby
|
|
162
195
|
end
|
163
196
|
|
164
197
|
p_stdin.close
|
165
|
-
self.last_status = wait_thread.value
|
198
|
+
self.last_status = T.cast(wait_thread.value, Process::Status)
|
166
199
|
run_after_callbacks(cmd)
|
167
200
|
wait_thread.join
|
168
201
|
end
|
@@ -170,26 +203,32 @@ module Kuby
|
|
170
203
|
result.string
|
171
204
|
end
|
172
205
|
|
206
|
+
sig { params(cmd: T::Array[String]).void }
|
173
207
|
def run_before_callbacks(cmd)
|
174
208
|
(@before_execute || []).each { |cb| cb.call(cmd) }
|
175
209
|
end
|
176
210
|
|
211
|
+
sig { params(cmd: T::Array[String]).void }
|
177
212
|
def run_after_callbacks(cmd)
|
178
213
|
(@after_execute || []).each { |cb| cb.call(cmd, last_status) }
|
179
214
|
end
|
180
215
|
|
216
|
+
sig { params(status: Process::Status).void }
|
181
217
|
def last_status=(status)
|
182
218
|
Thread.current[status_key] = status
|
183
219
|
end
|
184
220
|
|
221
|
+
sig { returns(Symbol) }
|
185
222
|
def status_key
|
186
223
|
raise NotImplementedError, "#{__method__} must be defined in derived classes"
|
187
224
|
end
|
188
225
|
|
226
|
+
sig { returns(Symbol) }
|
189
227
|
def stdout_key
|
190
228
|
raise NotImplementedError, "#{__method__} must be defined in derived classes"
|
191
229
|
end
|
192
230
|
|
231
|
+
sig { returns(Symbol) }
|
193
232
|
def stderr_key
|
194
233
|
raise NotImplementedError, "#{__method__} must be defined in derived classes"
|
195
234
|
end
|
data/lib/kuby/commands.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
|
+
|
2
3
|
require 'kuby/version'
|
3
4
|
require 'gli'
|
4
5
|
|
5
6
|
module Kuby
|
6
7
|
class Commands
|
8
|
+
extend T::Sig
|
7
9
|
extend GLI::App
|
8
10
|
|
9
11
|
# GLI doesn't have a wildcard option, so it's impossible to tell it to
|
@@ -17,8 +19,12 @@ module Kuby
|
|
17
19
|
# avoid the usual series of cryptic alias_method calls (note that there
|
18
20
|
# is no singleton class version of #prepend in the Ruby language).
|
19
21
|
singleton_class.send(:prepend, Module.new do
|
22
|
+
extend T::Sig
|
23
|
+
|
24
|
+
sig { params(args: T::Array[String]).void }
|
20
25
|
def run(args)
|
21
26
|
if idx = args.index('rails') || idx = args.index('rake')
|
27
|
+
@rails_options = T.let(@rails_options, T.nilable(T::Array[String]))
|
22
28
|
@rails_options = args[idx..-1]
|
23
29
|
super(args[0..idx])
|
24
30
|
else
|
@@ -27,10 +33,12 @@ module Kuby
|
|
27
33
|
end
|
28
34
|
end)
|
29
35
|
|
36
|
+
sig { returns(Kuby::Tasks) }
|
30
37
|
def self.tasks
|
31
38
|
Kuby::Tasks.new(Kuby.environment)
|
32
39
|
end
|
33
40
|
|
41
|
+
sig { void }
|
34
42
|
def self.must_be_dev_env!
|
35
43
|
unless Kuby.environment.development?
|
36
44
|
fail "Command not supported in the '#{Kuby.environment.name}' environment"
|
@@ -67,6 +75,7 @@ module Kuby
|
|
67
75
|
rc.action do |global_options, options, args|
|
68
76
|
must_be_dev_env!
|
69
77
|
exit 1 unless tasks.dev_deployment_ok
|
78
|
+
@rails_options = T.let(@rails_options, T.nilable(T::Array[String]))
|
70
79
|
Kuby::RailsCommands.run(@rails_options)
|
71
80
|
end
|
72
81
|
|
data/lib/kuby/definition.rb
CHANGED
@@ -1,12 +1,24 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
|
+
|
2
3
|
module Kuby
|
3
4
|
class Definition
|
5
|
+
extend T::Sig
|
6
|
+
|
7
|
+
sig { returns(String) }
|
4
8
|
attr_reader :app_name
|
5
9
|
|
10
|
+
sig { params(app_name: String, block: T.nilable(T.proc.void)).void }
|
6
11
|
def initialize(app_name, &block)
|
7
12
|
@app_name = app_name
|
13
|
+
@environments = T.let(@environments, T.nilable(T::Hash[Symbol, Environment]))
|
8
14
|
end
|
9
15
|
|
16
|
+
sig {
|
17
|
+
params(
|
18
|
+
name: Symbol,
|
19
|
+
block: T.nilable(T.proc.void)
|
20
|
+
).returns(Environment)
|
21
|
+
}
|
10
22
|
def environment(name = Kuby.env, &block)
|
11
23
|
name = name.to_s
|
12
24
|
|
@@ -16,9 +28,10 @@ module Kuby
|
|
16
28
|
environments[name].instance_eval(&block)
|
17
29
|
end
|
18
30
|
|
19
|
-
environments[name]
|
31
|
+
T.must(environments[name])
|
20
32
|
end
|
21
33
|
|
34
|
+
sig { returns(T::Hash[Symbol, Environment]) }
|
22
35
|
def environments
|
23
36
|
@environments ||= {}
|
24
37
|
end
|
data/lib/kuby/dev_setup.rb
CHANGED
@@ -1,19 +1,34 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
|
+
|
2
3
|
module Kuby
|
3
4
|
class Spinner
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
extend T::Sig
|
6
|
+
|
7
|
+
PIECES = T.let(%w(- \\ | /).freeze, T::Array[String])
|
8
|
+
INTERVAL = T.let(0.2, Float) # seconds
|
9
|
+
|
10
|
+
sig {
|
11
|
+
params(
|
12
|
+
message: String,
|
13
|
+
block: T.proc.params(spinner: Spinner).void
|
14
|
+
)
|
15
|
+
.void
|
16
|
+
}
|
17
|
+
def self.spin(message, &block)
|
8
18
|
yield new(message)
|
9
19
|
end
|
10
20
|
|
11
|
-
|
21
|
+
sig { returns(String) }
|
22
|
+
attr_reader :message
|
23
|
+
|
24
|
+
sig { returns(Symbol) }
|
25
|
+
attr_reader :status
|
12
26
|
|
27
|
+
sig { params(message: String).void }
|
13
28
|
def initialize(message)
|
14
|
-
@message = message
|
15
|
-
@status = :running
|
16
|
-
@thread = Thread.new do
|
29
|
+
@message = T.let(message, String)
|
30
|
+
@status = T.let(:running, Symbol)
|
31
|
+
@thread = T.let(Thread.new do
|
17
32
|
counter = 0
|
18
33
|
|
19
34
|
while true
|
@@ -33,14 +48,16 @@ module Kuby
|
|
33
48
|
end
|
34
49
|
|
35
50
|
puts
|
36
|
-
end
|
51
|
+
end, Thread)
|
37
52
|
end
|
38
53
|
|
54
|
+
sig { void }
|
39
55
|
def success
|
40
56
|
@status = :success
|
41
57
|
@thread.join
|
42
58
|
end
|
43
59
|
|
60
|
+
sig { void }
|
44
61
|
def failure
|
45
62
|
@status = :failure
|
46
63
|
@thread.join
|
@@ -48,66 +65,116 @@ module Kuby
|
|
48
65
|
end
|
49
66
|
|
50
67
|
class SetupTask
|
51
|
-
|
68
|
+
extend T::Sig
|
52
69
|
|
70
|
+
sig { returns(String) }
|
71
|
+
attr_reader :message
|
72
|
+
|
73
|
+
sig { returns(T.proc.void) }
|
74
|
+
attr_reader :callable
|
75
|
+
|
76
|
+
sig { params(message: String, callable: T.proc.void).void }
|
53
77
|
def initialize(message, callable)
|
54
78
|
@message = message
|
55
79
|
@callable = callable
|
56
80
|
end
|
57
81
|
|
82
|
+
sig { void }
|
58
83
|
def run
|
59
84
|
callable.call
|
60
85
|
end
|
61
86
|
end
|
62
87
|
|
63
88
|
class Pipe
|
64
|
-
|
89
|
+
extend T::Sig
|
90
|
+
|
91
|
+
sig { returns(Symbol) }
|
92
|
+
attr_reader :name
|
93
|
+
|
94
|
+
sig { returns(T.untyped) }
|
95
|
+
attr_reader :cli
|
65
96
|
|
97
|
+
sig { returns(StringIO) }
|
98
|
+
attr_reader :out
|
99
|
+
|
100
|
+
sig { returns(StringIO) }
|
101
|
+
attr_reader :err
|
102
|
+
|
103
|
+
sig { params(name: Symbol, cli: T.untyped).void }
|
66
104
|
def initialize(name, cli)
|
67
|
-
@name = name
|
68
|
-
@cli = cli
|
69
|
-
@out = StringIO.new
|
70
|
-
@err = StringIO.new
|
105
|
+
@name = T.let(name, Symbol)
|
106
|
+
@cli = T.let(cli, T.untyped)
|
107
|
+
@out = T.let(StringIO.new, StringIO)
|
108
|
+
@err = T.let(StringIO.new, StringIO)
|
71
109
|
end
|
72
110
|
|
111
|
+
sig { params(block: T.proc.void).void }
|
73
112
|
def wrap(&block)
|
74
113
|
cli.with_pipes(out, err) do
|
75
114
|
block.call
|
76
115
|
end
|
77
116
|
end
|
78
117
|
|
118
|
+
sig { returns(T::Boolean) }
|
79
119
|
def success?
|
80
120
|
cli.last_status.nil? || cli.last_status.success?
|
81
121
|
end
|
82
122
|
end
|
83
123
|
|
84
124
|
class Pipes
|
125
|
+
extend T::Sig
|
126
|
+
extend T::Generic
|
127
|
+
|
85
128
|
include Enumerable
|
86
129
|
|
87
|
-
|
130
|
+
Elem = type_member(fixed: Pipe)
|
131
|
+
|
132
|
+
sig { returns(T::Array[Pipe]) }
|
133
|
+
attr_reader :pipes
|
88
134
|
|
135
|
+
sig { returns(T.nilable(StandardError)) }
|
136
|
+
attr_reader :ex
|
137
|
+
|
138
|
+
sig { params(clis: T::Hash[Symbol, T.untyped]).returns(Pipes) }
|
89
139
|
def self.build(clis)
|
90
140
|
new(clis.map { |name, cli| Pipe.new(name, cli) })
|
91
141
|
end
|
92
142
|
|
143
|
+
sig { params(pipes: T::Array[Pipe]).void }
|
93
144
|
def initialize(pipes)
|
94
|
-
@
|
145
|
+
@ex = T.let(@ex, T.nilable(StandardError))
|
146
|
+
@pipes = T.let(pipes, T::Array[Pipe])
|
95
147
|
end
|
96
148
|
|
149
|
+
sig {
|
150
|
+
override.params(
|
151
|
+
block: T.proc.params(package: Pipe).void
|
152
|
+
)
|
153
|
+
.void
|
154
|
+
}
|
97
155
|
def each(&block)
|
98
156
|
pipes.each(&block)
|
99
157
|
end
|
100
158
|
|
159
|
+
sig { params(block: T.proc.void).void }
|
101
160
|
def wrap(&block)
|
102
161
|
do_wrap(pipes, &block)
|
103
162
|
end
|
104
163
|
|
164
|
+
sig { returns(T::Boolean) }
|
105
165
|
def success?
|
106
166
|
pipes.all?(&:success?) && !ex
|
107
167
|
end
|
108
168
|
|
109
169
|
private
|
110
170
|
|
171
|
+
sig {
|
172
|
+
params(
|
173
|
+
remaining_pipes: T::Array[Pipe],
|
174
|
+
block: T.proc.void
|
175
|
+
)
|
176
|
+
.void
|
177
|
+
}
|
111
178
|
def do_wrap(remaining_pipes, &block)
|
112
179
|
if remaining_pipes.empty?
|
113
180
|
begin
|
@@ -119,20 +186,28 @@ module Kuby
|
|
119
186
|
return
|
120
187
|
end
|
121
188
|
|
122
|
-
remaining_pipes[0].wrap do
|
123
|
-
do_wrap(remaining_pipes[1..-1], &block)
|
189
|
+
T.must(remaining_pipes[0]).wrap do
|
190
|
+
do_wrap(T.must(remaining_pipes[1..-1]), &block)
|
124
191
|
end
|
125
192
|
end
|
126
193
|
end
|
127
194
|
|
128
195
|
class SetupTaskList
|
129
|
-
|
196
|
+
extend T::Sig
|
197
|
+
|
198
|
+
sig { returns(T::Array[SetupTask]) }
|
199
|
+
attr_reader :tasks
|
130
200
|
|
201
|
+
sig { returns T::Hash[Symbol, T.untyped] }
|
202
|
+
attr_reader :clis
|
203
|
+
|
204
|
+
sig { params(tasks: T::Array[SetupTask], clis: T::Hash[Symbol, T.untyped]).void }
|
131
205
|
def initialize(tasks, clis)
|
132
206
|
@tasks = tasks
|
133
207
|
@clis = clis
|
134
208
|
end
|
135
209
|
|
210
|
+
sig { void }
|
136
211
|
def run
|
137
212
|
tasks.each do |task|
|
138
213
|
pipes = Pipes.build(clis)
|
@@ -160,6 +235,7 @@ module Kuby
|
|
160
235
|
|
161
236
|
private
|
162
237
|
|
238
|
+
sig { params(pipe: Pipe).void }
|
163
239
|
def print_streams(pipe)
|
164
240
|
unless pipe.out.string.strip.empty?
|
165
241
|
puts("========= #{pipe.name.upcase} STDOUT ========")
|
@@ -172,27 +248,37 @@ module Kuby
|
|
172
248
|
end
|
173
249
|
end
|
174
250
|
|
251
|
+
sig { params(ex: T.nilable(StandardError)).void }
|
175
252
|
def print_error(ex)
|
176
253
|
return unless ex
|
177
254
|
puts("========= RUBY ERROR ========")
|
178
255
|
puts(ex.message)
|
179
|
-
puts(ex.backtrace.join("\n"))
|
256
|
+
puts(T.must(ex.backtrace).join("\n"))
|
180
257
|
end
|
181
258
|
end
|
182
259
|
|
183
260
|
class DevSetup
|
261
|
+
extend T::Sig
|
262
|
+
|
263
|
+
sig { returns(Environment) }
|
184
264
|
attr_reader :environment
|
185
265
|
|
266
|
+
sig { params(environment: Environment).void }
|
186
267
|
def initialize(environment)
|
187
|
-
@environment = environment
|
268
|
+
@environment = T.let(environment, Environment)
|
269
|
+
@setup_tasks = T.let(@setup_tasks, T.nilable(T::Array[SetupTask]))
|
270
|
+
@clis = T.let(@clis, T.nilable(T::Hash[Symbol, T.untyped]))
|
271
|
+
@tasks = T.let(@tasks, T.nilable(Tasks))
|
188
272
|
end
|
189
273
|
|
274
|
+
sig { void }
|
190
275
|
def run
|
191
276
|
SetupTaskList.new(setup_tasks, clis).run
|
192
277
|
end
|
193
278
|
|
194
279
|
private
|
195
280
|
|
281
|
+
sig { returns(T::Array[SetupTask]) }
|
196
282
|
def setup_tasks
|
197
283
|
@setup_tasks ||= [
|
198
284
|
SetupTask.new(
|
@@ -231,14 +317,17 @@ module Kuby
|
|
231
317
|
]
|
232
318
|
end
|
233
319
|
|
320
|
+
sig { returns(Kubernetes::Spec) }
|
234
321
|
def kubernetes
|
235
322
|
environment.kubernetes
|
236
323
|
end
|
237
324
|
|
325
|
+
sig { returns(Docker::Spec) }
|
238
326
|
def docker
|
239
327
|
environment.docker
|
240
328
|
end
|
241
329
|
|
330
|
+
sig { returns T::Hash[Symbol, T.untyped] }
|
242
331
|
def clis
|
243
332
|
@clis ||= {
|
244
333
|
kubectl: kubernetes.provider.kubernetes_cli,
|
@@ -249,6 +338,7 @@ module Kuby
|
|
249
338
|
}
|
250
339
|
end
|
251
340
|
|
341
|
+
sig { returns(Tasks) }
|
252
342
|
def tasks
|
253
343
|
@tasks ||= Kuby::Tasks.new(environment)
|
254
344
|
end
|
data/lib/kuby/docker/cli.rb
CHANGED
@@ -35,13 +35,13 @@ module Kuby
|
|
35
35
|
executable, 'login', url, '--username', username, '--password-stdin'
|
36
36
|
]
|
37
37
|
|
38
|
-
open3_w(
|
38
|
+
open3_w(cmd) do |stdin, _wait_threads|
|
39
39
|
stdin.puts(password)
|
40
40
|
end
|
41
41
|
|
42
|
-
unless last_status.success?
|
42
|
+
unless T.must(last_status).success?
|
43
43
|
raise LoginError, 'build failed: docker command exited with '\
|
44
|
-
"status code #{last_status.exitstatus}"
|
44
|
+
"status code #{T.must(last_status).exitstatus}"
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
@@ -72,13 +72,13 @@ module Kuby
|
|
72
72
|
'-f-', '.'
|
73
73
|
]
|
74
74
|
|
75
|
-
open3_w(
|
75
|
+
open3_w(cmd) do |stdin, _wait_threads|
|
76
76
|
stdin.puts(dockerfile.to_s)
|
77
77
|
end
|
78
78
|
|
79
|
-
unless last_status.success?
|
79
|
+
unless T.must(last_status).success?
|
80
80
|
raise BuildError, 'build failed: docker command exited with '\
|
81
|
-
"status code #{last_status.exitstatus}"
|
81
|
+
"status code #{T.must(last_status).exitstatus}"
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
@@ -124,9 +124,9 @@ module Kuby
|
|
124
124
|
executable, 'push', "#{image_url}:#{tag}"
|
125
125
|
])
|
126
126
|
|
127
|
-
unless last_status.success?
|
127
|
+
unless T.must(last_status).success?
|
128
128
|
raise PushError, 'push failed: docker command exited with '\
|
129
|
-
"status code #{last_status.exitstatus}"
|
129
|
+
"status code #{T.must(last_status).exitstatus}"
|
130
130
|
end
|
131
131
|
end
|
132
132
|
|
@@ -136,9 +136,9 @@ module Kuby
|
|
136
136
|
executable, 'pull', "#{image_url}:#{tag}"
|
137
137
|
])
|
138
138
|
|
139
|
-
unless last_status.success?
|
139
|
+
unless T.must(last_status).success?
|
140
140
|
raise PullError, 'pull failed: docker command exited with '\
|
141
|
-
"status code #{last_status.exitstatus}"
|
141
|
+
"status code #{T.must(last_status).exitstatus}"
|
142
142
|
end
|
143
143
|
end
|
144
144
|
|
data/lib/kuby/docker/dev_spec.rb
CHANGED
@@ -5,16 +5,16 @@ module Kuby
|
|
5
5
|
class WebserverDevPhase < Layer
|
6
6
|
extend T::Sig
|
7
7
|
|
8
|
-
DEFAULT_PORT = T.let(
|
8
|
+
DEFAULT_PORT = T.let(3000, Integer)
|
9
9
|
|
10
|
-
sig { params(port:
|
10
|
+
sig { params(port: Integer).void }
|
11
11
|
attr_writer :port
|
12
12
|
|
13
13
|
sig { params(environment: Environment).void }
|
14
14
|
def initialize(environment)
|
15
15
|
super
|
16
16
|
|
17
|
-
@port = T.let(@port, T.nilable(
|
17
|
+
@port = T.let(@port, T.nilable(Integer))
|
18
18
|
end
|
19
19
|
|
20
20
|
sig { override.params(dockerfile: Dockerfile).void }
|
@@ -22,7 +22,7 @@ module Kuby
|
|
22
22
|
dockerfile.expose(port)
|
23
23
|
end
|
24
24
|
|
25
|
-
sig { returns(
|
25
|
+
sig { returns(Integer) }
|
26
26
|
def port
|
27
27
|
@port || DEFAULT_PORT
|
28
28
|
end
|
@@ -75,7 +75,7 @@ module Kuby
|
|
75
75
|
@distro_spec = nil
|
76
76
|
end
|
77
77
|
|
78
|
-
sig { params(port:
|
78
|
+
sig { params(port: Integer).void }
|
79
79
|
def port(port)
|
80
80
|
webserver_phase.port = port
|
81
81
|
end
|
@@ -115,6 +115,13 @@ module Kuby
|
|
115
115
|
layer_stack.includes?(name)
|
116
116
|
end
|
117
117
|
|
118
|
+
sig {
|
119
|
+
params(block: T.nilable(T.proc.void)).returns(Credentials)
|
120
|
+
}
|
121
|
+
def credentials(&block)
|
122
|
+
raise 'Docker credentials are not supported in the development environment'
|
123
|
+
end
|
124
|
+
|
118
125
|
sig { returns(Dockerfile) }
|
119
126
|
def to_dockerfile
|
120
127
|
Dockerfile.new.tap do |df|
|
@@ -10,10 +10,10 @@ module Kuby
|
|
10
10
|
class Command
|
11
11
|
extend T::Sig
|
12
12
|
|
13
|
-
sig { returns(T::Array[String]) }
|
13
|
+
sig { returns(T::Array[T.any(String, Integer)]) }
|
14
14
|
attr_reader :args
|
15
15
|
|
16
|
-
sig { params(args: T::Array[String]).void }
|
16
|
+
sig { params(args: T::Array[T.any(String, Integer)]).void }
|
17
17
|
def initialize(args)
|
18
18
|
@args = args
|
19
19
|
end
|
@@ -143,9 +143,9 @@ module Kuby
|
|
143
143
|
add Copy.new(source, dest, from: from)
|
144
144
|
end
|
145
145
|
|
146
|
-
sig { params(
|
147
|
-
def expose(
|
148
|
-
add Expose.new(
|
146
|
+
sig { params(port: Integer).void }
|
147
|
+
def expose(port)
|
148
|
+
add Expose.new([port])
|
149
149
|
end
|
150
150
|
|
151
151
|
sig { params(args: String).void }
|
@@ -164,11 +164,11 @@ module Kuby
|
|
164
164
|
Digest::SHA256.hexdigest(to_s)
|
165
165
|
end
|
166
166
|
|
167
|
-
sig { returns(T::Array[
|
167
|
+
sig { returns(T::Array[Integer]) }
|
168
168
|
def exposed_ports
|
169
169
|
commands
|
170
170
|
.select { |c| c.is_a?(Expose) }
|
171
|
-
.map { |c| T.
|
171
|
+
.map { |c| T.cast(c.args.first, Integer) }
|
172
172
|
end
|
173
173
|
|
174
174
|
sig { params(pos: Integer, block: T.proc.void).void }
|
data/lib/kuby/docker/spec.rb
CHANGED
@@ -30,7 +30,7 @@ module Kuby
|
|
30
30
|
'puma',
|
31
31
|
'--workers', '4',
|
32
32
|
'--bind', 'tcp://0.0.0.0',
|
33
|
-
'--port', phase.port,
|
33
|
+
'--port', phase.port.to_s,
|
34
34
|
'--pidfile', './server.pid',
|
35
35
|
'./config.ru'
|
36
36
|
)
|
@@ -39,10 +39,10 @@ module Kuby
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
DEFAULT_PORT = T.let(
|
42
|
+
DEFAULT_PORT = T.let(8080, Integer)
|
43
43
|
WEBSERVER_MAP = T.let({ puma: Puma }.freeze, T::Hash[Symbol, T.class_of(Webserver)])
|
44
44
|
|
45
|
-
sig { params(port:
|
45
|
+
sig { params(port: Integer).void }
|
46
46
|
attr_writer :port
|
47
47
|
|
48
48
|
sig { returns(T.nilable(Symbol)) }
|
@@ -55,7 +55,7 @@ module Kuby
|
|
55
55
|
def initialize(environment)
|
56
56
|
super
|
57
57
|
|
58
|
-
@port = T.let(@port, T.nilable(
|
58
|
+
@port = T.let(@port, T.nilable(Integer))
|
59
59
|
@webserver = T.let(@webserver, T.nilable(Symbol))
|
60
60
|
end
|
61
61
|
|
@@ -68,7 +68,7 @@ module Kuby
|
|
68
68
|
ws_class.new(self).apply_to(dockerfile)
|
69
69
|
end
|
70
70
|
|
71
|
-
sig { returns(
|
71
|
+
sig { returns(Integer) }
|
72
72
|
def port
|
73
73
|
@port || DEFAULT_PORT
|
74
74
|
end
|
data/lib/kuby/kubernetes/spec.rb
CHANGED
@@ -18,13 +18,28 @@ module Kuby
|
|
18
18
|
|
19
19
|
def provider(provider_name = nil, &block)
|
20
20
|
if provider_name
|
21
|
-
|
22
|
-
|
21
|
+
provider_klass = Kuby.providers[provider_name]
|
22
|
+
|
23
|
+
unless provider_klass
|
24
|
+
begin
|
25
|
+
# attempt to auto-require
|
26
|
+
require "kuby/#{provider_name}"
|
27
|
+
provider_klass = Kuby.providers[provider_name]
|
28
|
+
rescue LoadError
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
if provider_klass
|
33
|
+
if !@provider || !@provider.is_a?(provider_klass)
|
34
|
+
@provider = provider_klass.new(environment)
|
35
|
+
end
|
36
|
+
|
23
37
|
@provider.configure(&block)
|
24
38
|
else
|
25
39
|
msg = if provider_name
|
26
40
|
"no provider registered with name #{provider_name}, "\
|
27
|
-
'do you need to add a gem to your Gemfile
|
41
|
+
'do you need to add a gem to your Gemfile and/or a '\
|
42
|
+
'require statement to your Kuby config?'
|
28
43
|
else
|
29
44
|
'no provider configured'
|
30
45
|
end
|
@@ -3,7 +3,25 @@ require 'rails/generators'
|
|
3
3
|
require 'rails/generators/base'
|
4
4
|
|
5
5
|
class KubyGenerator < Rails::Generators::Base
|
6
|
+
def create_initializer_file
|
7
|
+
create_file(
|
8
|
+
File.join(*%w(config initializers kuby.rb)),
|
9
|
+
<<~END
|
10
|
+
require 'kuby'
|
11
|
+
Kuby.load!
|
12
|
+
END
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
6
16
|
def create_config_file
|
17
|
+
app_class = Rails.application.class
|
18
|
+
|
19
|
+
app_name = if app_class.respond_to?(:module_parent_name)
|
20
|
+
app_class.module_parent_name
|
21
|
+
else
|
22
|
+
app_class.parent_name
|
23
|
+
end
|
24
|
+
|
7
25
|
create_file(
|
8
26
|
'kuby.rb',
|
9
27
|
<<~END
|
@@ -11,7 +29,7 @@ class KubyGenerator < Rails::Generators::Base
|
|
11
29
|
require 'active_support/encrypted_configuration'
|
12
30
|
|
13
31
|
# Define a production Kuby deploy environment
|
14
|
-
Kuby.define('#{
|
32
|
+
Kuby.define('#{app_name}') do
|
15
33
|
environment(:production) do
|
16
34
|
# Because the Rails environment isn't always loaded when
|
17
35
|
# your Kuby config is loaded, provide access to Rails
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# typed: true
|
2
|
+
|
2
3
|
module Kuby
|
3
4
|
module Plugins
|
4
5
|
module RailsApp
|
@@ -14,6 +15,18 @@ module Kuby
|
|
14
15
|
environment.docker.package_phase.add(:sqlite_client)
|
15
16
|
end
|
16
17
|
|
18
|
+
def requires_credentials?
|
19
|
+
false
|
20
|
+
end
|
21
|
+
|
22
|
+
def user(_user)
|
23
|
+
raise 'SQLite databases do not require a username or password'
|
24
|
+
end
|
25
|
+
|
26
|
+
def password(_password)
|
27
|
+
raise 'SQLite databases do not require a username or password'
|
28
|
+
end
|
29
|
+
|
17
30
|
def name
|
18
31
|
:sqlite
|
19
32
|
end
|
data/lib/kuby/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kuby-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
4
|
+
version: 0.11.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cameron Dutro
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-10-
|
11
|
+
date: 2020-10-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|