kuby-core 0.11.16 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/Gemfile +1 -2
  4. data/kuby-core.gemspec +1 -1
  5. data/lib/kuby.rb +2 -20
  6. data/lib/kuby/commands.rb +13 -67
  7. data/lib/kuby/docker.rb +27 -25
  8. data/lib/kuby/docker/alpine.rb +2 -1
  9. data/lib/kuby/docker/app_image.rb +19 -0
  10. data/lib/kuby/docker/cli.rb +4 -12
  11. data/lib/kuby/docker/docker_uri.rb +18 -7
  12. data/lib/kuby/docker/errors.rb +1 -19
  13. data/lib/kuby/docker/image.rb +115 -0
  14. data/lib/kuby/docker/layer.rb +0 -7
  15. data/lib/kuby/docker/local_tags.rb +9 -10
  16. data/lib/kuby/docker/package_phase.rb +0 -5
  17. data/lib/kuby/docker/packages.rb +1 -0
  18. data/lib/kuby/docker/remote_tags.rb +10 -5
  19. data/lib/kuby/docker/setup_phase.rb +17 -9
  20. data/lib/kuby/docker/spec.rb +29 -62
  21. data/lib/kuby/docker/timestamp_tag.rb +8 -1
  22. data/lib/kuby/docker/timestamped_image.rb +113 -0
  23. data/lib/kuby/environment.rb +1 -10
  24. data/lib/kuby/kubernetes/bare_metal_provider.rb +16 -4
  25. data/lib/kuby/kubernetes/deployer.rb +1 -1
  26. data/lib/kuby/kubernetes/docker_desktop_provider.rb +0 -15
  27. data/lib/kuby/kubernetes/spec.rb +21 -17
  28. data/lib/kuby/plugin.rb +2 -2
  29. data/lib/kuby/plugins/rails_app.rb +1 -0
  30. data/lib/kuby/plugins/rails_app/assets.rb +60 -70
  31. data/lib/kuby/plugins/rails_app/assets_image.rb +55 -0
  32. data/lib/kuby/plugins/rails_app/plugin.rb +53 -236
  33. data/lib/kuby/tasks.rb +30 -69
  34. data/lib/kuby/version.rb +1 -1
  35. data/spec/docker/spec_spec.rb +9 -118
  36. data/spec/docker/timestamped_image_spec.rb +123 -0
  37. data/spec/spec_helper.rb +10 -11
  38. metadata +9 -10
  39. data/lib/kuby/dev_setup.rb +0 -346
  40. data/lib/kuby/docker/dev_spec.rb +0 -202
  41. data/lib/kuby/docker/metadata.rb +0 -90
  42. data/lib/kuby/docker/tags.rb +0 -92
  43. data/lib/kuby/rails_commands.rb +0 -84
  44. data/spec/docker/metadata_spec.rb +0 -73
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 01cc5428a8bc4bfc44143f4aa2c2e949405d3c7231831da50f33efa5a314fc29
4
- data.tar.gz: c4e440506c9ad072449f3382bcfa7dd1f80c757e64426b5c49f1e20540c57ae8
3
+ metadata.gz: 4a072588afc0cc4e0cf815c276628b90c192bf24310ed6c4c53089bc467ba278
4
+ data.tar.gz: 364b1265256eda0eea1f57469f241a1c78f1bdb2be0d37d8a23b5c6f01f4ff43
5
5
  SHA512:
6
- metadata.gz: 5db95c1958618d58354ba4c87411a0cd52894ede6ba0fbd622479e66e327397967314979c7496806577115d6b22571582e17f76c720a8472c9568cb009682555
7
- data.tar.gz: 2c1c1bd58fcbc7d29380e5e2ef2cf71b68f7073dbff26ca5d73333734b326dccc42243a559b3272502b4a6628db0c7513ea9b6586b5475e44108ba4a490734f5
6
+ metadata.gz: 866438d8c0880d949150d337b01fce94dfab9d0606ab3e2358e4c7cad376bb36cb3ff958ea72188967abf1192216c3b7586ddcfba6d7e0324ab4fbe37a085e49
7
+ data.tar.gz: 87e438bd3f4783b1b3d0e7609d773f5eeee91f7b9ae980446c8ca63084bddeb3a525d944750fe13fb36e98d782188cf6bd06c3df5edff742d8a1d5d80aa53966
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## 0.12.0
2
+ * Fix issue causing volume mount errors when k8s tries to schedule asset pods on multiple nodes (fixes #42).
3
+ - Persistent volumes can only be mounted on a single physical node.
4
+ - Kuby now creates a separate assets image powered by nginx.
5
+ - Ingress routes requests to either the Rails service or assets service depending on the URL (i.e. /assets).
6
+ - 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.
7
+ * Plugins can now specify additional Dockerfiles to build during `kuby build`.
8
+ * Switch from TravisCI to Github Actions.
9
+ * Remove support for development environments.
10
+ - Proved to be too difficult to maintain.
11
+ - Kuby is a _deployment_ tool anyway, not a dev tool.
12
+ - Maybe we can turn the dev stuff into a gem at some point.
13
+ * Refactor Docker image logic.
14
+ - Introduced the `Image` class and friends.
15
+ - Deleted the `Kuby::Docker::Metadata` class.
16
+ * Add missing git dependency to Alpine distro.
17
+ * Add a bare metal provider (fixes #10).
18
+
1
19
  ## 0.11.16
2
20
  * Fix yarn phase
3
21
  - 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.6397'
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/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.5'
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.rb CHANGED
@@ -13,7 +13,6 @@ module Kuby
13
13
  autoload :CLIBase, 'kuby/cli_base'
14
14
  autoload :Commands, 'kuby/commands'
15
15
  autoload :Definition, 'kuby/definition'
16
- autoload :DevSetup, 'kuby/dev_setup'
17
16
  autoload :Docker, 'kuby/docker'
18
17
  autoload :Environment, 'kuby/environment'
19
18
  autoload :Kubernetes, 'kuby/kubernetes'
@@ -21,7 +20,6 @@ module Kuby
21
20
  autoload :Plugin, 'kuby/plugin'
22
21
  autoload :PluginRegistry, 'kuby/plugin_registry'
23
22
  autoload :Plugins, 'kuby/plugins'
24
- autoload :RailsCommands, 'kuby/rails_commands'
25
23
  autoload :Tasks, 'kuby/tasks'
26
24
  autoload :TrailingHash, 'kuby/trailing_hash'
27
25
 
@@ -52,24 +50,6 @@ module Kuby
52
50
  @definition = Definition.new(name.to_s)
53
51
  @definition.instance_eval(&block)
54
52
 
55
- # default development environment
56
- @definition.environment(:development) do
57
- kubernetes do
58
- add_plugin(:rails_app) do
59
- tls_enabled false
60
-
61
- database do
62
- if requires_credentials?
63
- user(DEFAULT_DB_USER)
64
- password(DEFAULT_DB_PASSWORD)
65
- end
66
- end
67
- end
68
-
69
- provider :docker_desktop
70
- end
71
- end
72
-
73
53
  @definition.environments.each do |_, env|
74
54
  env.kubernetes.after_configuration
75
55
  end
@@ -174,3 +154,5 @@ Kuby.register_package(:c_toolchain,
174
154
  debian: 'build-essential',
175
155
  alpine: 'build-base'
176
156
  )
157
+
158
+ Kuby.register_package(:git, 'git')
data/lib/kuby/commands.rb CHANGED
@@ -38,13 +38,6 @@ module Kuby
38
38
  Kuby::Tasks.new(Kuby.environment)
39
39
  end
40
40
 
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
41
  program_desc 'Kuby command-line interface. Kuby is a convention '\
49
42
  'over configuration approach for running Rails apps in Kubernetes.'
50
43
 
@@ -68,59 +61,19 @@ module Kuby
68
61
  true
69
62
  end
70
63
 
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
64
  desc 'Builds the Docker image.'
121
65
  command :build do |c|
66
+ c.flag [:a, :arg], required: false, multiple: true
122
67
  c.action do |global_options, options, args|
123
- tasks.build
68
+ build_args = {}.tap do |build_args|
69
+ (options[:arg] || []).each do |a|
70
+ key, value = a.split('=')
71
+ value = value[1..-2] if value.start_with?('"') || value.start_with?("'")
72
+ build_args[key] = value
73
+ end
74
+ end
75
+
76
+ tasks.build(build_args)
124
77
  end
125
78
  end
126
79
 
@@ -138,10 +91,10 @@ module Kuby
138
91
  end
139
92
  end
140
93
 
141
- desc 'Prints the effective Dockerfile used to build the Docker image.'
142
- command :dockerfile do |c|
94
+ desc 'Prints the effective Dockerfiles used to build Docker images.'
95
+ command :dockerfiles do |c|
143
96
  c.action do |global_options, options, args|
144
- tasks.print_dockerfile
97
+ tasks.print_dockerfiles
145
98
  end
146
99
  end
147
100
 
@@ -197,7 +150,6 @@ module Kuby
197
150
  rc.desc 'Tails (i.e. continuously streams) the Rails log from your running application.'
198
151
  rc.command :logs do |c|
199
152
  c.action do |global_options, options, args|
200
- exit 1 unless tasks.dev_deployment_ok
201
153
  tasks.remote_logs
202
154
  end
203
155
  end
@@ -205,7 +157,6 @@ module Kuby
205
157
  rc.desc 'Lists running Kubernetes pods.'
206
158
  rc.command :status do |c|
207
159
  c.action do |global_options, options, args|
208
- exit 1 unless tasks.dev_deployment_ok
209
160
  tasks.remote_status
210
161
  end
211
162
  end
@@ -213,7 +164,6 @@ module Kuby
213
164
  rc.desc 'Runs an arbitrary command inside a running Rails pod.'
214
165
  rc.command :exec do |c|
215
166
  c.action do |global_options, options, args|
216
- exit 1 unless tasks.dev_deployment_ok
217
167
  tasks.remote_exec(args)
218
168
  end
219
169
  end
@@ -221,7 +171,6 @@ module Kuby
221
171
  rc.desc 'Establishes a shell inside a running Rails pod.'
222
172
  rc.command :shell do |c|
223
173
  c.action do |global_options, options, args|
224
- exit 1 unless tasks.dev_deployment_ok
225
174
  tasks.remote_shell
226
175
  end
227
176
  end
@@ -229,7 +178,6 @@ module Kuby
229
178
  rc.desc 'Establishes a Rails console inside a running Rails pod.'
230
179
  rc.command :console do |c|
231
180
  c.action do |global_options, options, args|
232
- exit 1 unless tasks.dev_deployment_ok
233
181
  tasks.remote_console
234
182
  end
235
183
  end
@@ -237,7 +185,6 @@ module Kuby
237
185
  rc.desc 'Establishes a database console inside a running Rails pod.'
238
186
  rc.command :dbconsole do |c|
239
187
  c.action do |global_options, options, args|
240
- exit 1 unless tasks.dev_deployment_ok
241
188
  tasks.remote_dbconsole
242
189
  end
243
190
  end
@@ -245,7 +192,6 @@ module Kuby
245
192
  rc.desc "Restarts the Rails app's web pods."
246
193
  rc.command :restart do |c|
247
194
  c.action do |global_options, options, args|
248
- exit 1 unless tasks.dev_deployment_ok
249
195
  tasks.remote_restart
250
196
  end
251
197
  end
data/lib/kuby/docker.rb CHANGED
@@ -4,30 +4,32 @@ require 'kuby/docker/errors'
4
4
 
5
5
  module Kuby
6
6
  module Docker
7
- autoload :Alpine, 'kuby/docker/alpine'
8
- autoload :AssetsPhase, 'kuby/docker/assets_phase'
9
- autoload :BundlerPhase, 'kuby/docker/bundler_phase'
10
- autoload :CLI, 'kuby/docker/cli'
11
- autoload :CopyPhase, 'kuby/docker/copy_phase'
12
- autoload :Credentials, 'kuby/docker/credentials'
13
- autoload :Debian, 'kuby/docker/debian'
14
- autoload :DevSpec, 'kuby/docker/dev_spec'
15
- autoload :Distro, 'kuby/docker/distro'
16
- autoload :Dockerfile, 'kuby/docker/dockerfile'
17
- autoload :DockerURI, 'kuby/docker/docker_uri'
18
- autoload :InlineLayer, 'kuby/docker/inline_layer'
19
- autoload :Layer, 'kuby/docker/layer'
20
- autoload :LayerStack, 'kuby/docker/layer_stack'
21
- autoload :LocalTags, 'kuby/docker/local_tags'
22
- autoload :Metadata, 'kuby/docker/metadata'
23
- autoload :Packages, 'kuby/docker/packages'
24
- autoload :PackagePhase, 'kuby/docker/package_phase'
25
- autoload :RemoteTags, 'kuby/docker/remote_tags'
26
- autoload :SetupPhase, 'kuby/docker/setup_phase'
27
- autoload :Spec, 'kuby/docker/spec'
28
- autoload :Tags, 'kuby/docker/tags'
29
- autoload :TimestampTag, 'kuby/docker/timestamp_tag'
30
- autoload :WebserverPhase, 'kuby/docker/webserver_phase'
31
- autoload :YarnPhase, 'kuby/docker/yarn_phase'
7
+ LATEST_TAG = T.let('latest'.freeze, String)
8
+
9
+ autoload :Alpine, 'kuby/docker/alpine'
10
+ autoload :AppImage, 'kuby/docker/app_image'
11
+ autoload :AssetsPhase, 'kuby/docker/assets_phase'
12
+ autoload :BundlerPhase, 'kuby/docker/bundler_phase'
13
+ autoload :CLI, 'kuby/docker/cli'
14
+ autoload :CopyPhase, 'kuby/docker/copy_phase'
15
+ autoload :Credentials, 'kuby/docker/credentials'
16
+ autoload :Debian, 'kuby/docker/debian'
17
+ autoload :Distro, 'kuby/docker/distro'
18
+ autoload :Dockerfile, 'kuby/docker/dockerfile'
19
+ autoload :DockerURI, 'kuby/docker/docker_uri'
20
+ autoload :Image, 'kuby/docker/image'
21
+ autoload :InlineLayer, 'kuby/docker/inline_layer'
22
+ autoload :Layer, 'kuby/docker/layer'
23
+ autoload :LayerStack, 'kuby/docker/layer_stack'
24
+ autoload :LocalTags, 'kuby/docker/local_tags'
25
+ autoload :Packages, 'kuby/docker/packages'
26
+ autoload :PackagePhase, 'kuby/docker/package_phase'
27
+ autoload :RemoteTags, 'kuby/docker/remote_tags'
28
+ autoload :SetupPhase, 'kuby/docker/setup_phase'
29
+ autoload :Spec, 'kuby/docker/spec'
30
+ autoload :TimestampedImage, 'kuby/docker/timestamped_image'
31
+ autoload :TimestampTag, 'kuby/docker/timestamp_tag'
32
+ autoload :WebserverPhase, 'kuby/docker/webserver_phase'
33
+ autoload :YarnPhase, 'kuby/docker/yarn_phase'
32
34
  end
33
35
  end
@@ -10,7 +10,8 @@ module Kuby
10
10
  [:nodejs, '12.14.1'],
11
11
  [:yarn, '1.21.1'],
12
12
  [:c_toolchain, nil],
13
- [:tzdata, nil]
13
+ [:tzdata, nil],
14
+ [:git, nil]
14
15
  ].freeze, T::Array[[Symbol, T.nilable(String)]])
15
16
 
16
17
  sig { returns(Layer) }
@@ -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
@@ -53,19 +53,11 @@ module Kuby
53
53
  config.fetch('auths', {}).keys
54
54
  end
55
55
 
56
- sig {
57
- params(
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: false
1
+ # typed: strict
2
2
 
3
3
  module Kuby
4
4
  module Docker
5
5
  class DockerURI
6
- DEFAULT_REGISTRY_HOST = 'index.docker.io'.freeze
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
- attr_reader :host, :port, :path
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
@@ -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