kuby-core 0.16.1 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5cbd792443dc33de6a20d02f6969f6d59d535f1b68fb75c9a8945615fd870a28
4
- data.tar.gz: 3add1ef85d6758a2590d35d7aa0bfb4fffaeae55ef6567a34cf3b7557a56e55a
3
+ metadata.gz: 06ed279a1b0ecaac0daed1b868610bac67e6564611360de4cd841a24827438e2
4
+ data.tar.gz: f8616a5b0ab87c4fb71afa3afba0e001760b3c0855b7670b976013de3c1db5d6
5
5
  SHA512:
6
- metadata.gz: 7d855f57aae01d93c2fa44e285ee417ebcc00f12de6f9c4b989a39626ec9ec13a4659eafe0b8924592de5d860666158376e5adbf69c70373703eb2a9074ca75d
7
- data.tar.gz: dc553aa0b22e5ab262fa18fa1a60bebb421862eab7e747e06c63907fefe8f5371be56415d0bde2e959ffa775140b624aee3aa53006f1dbee272122c87bf53cc6
6
+ metadata.gz: d75bf991f55a97798152449606740b2d94c9a012ad7c17ea0b9b940c9ca9b3aad0e31baa4635ffeeec584144492d967054cdbfffa386c05c7427f1e90ac58e8f
7
+ data.tar.gz: 73b7718181d0e43ab1382c70a4a22da1835da30c887c2f42bc67bcce15d811aa0efab93df3a5fd6d28e2b2ce6d6dc3a73154a4cacdadcfeb9641ca0b2ba5604c
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 0.17.1
2
+ * Allow storage class to be customized when using the built-in bare metal provider.
3
+ * Fix a bug where the assets image would be built using the previous app image instead of the current one.
4
+ * Centralize the lookup of the Rails master key (not user-facing).
5
+ * Add descriptions to numerous CLI commands and their arguments.
6
+ * CLI now accepts multiple `--only` flags passed to subcommands like `build`, `push`, etc.
7
+ * Allow running setup steps for individual plugins.
8
+
1
9
  ## 0.16.1
2
10
  * Fix a few bugs caused by leaving `continue-on-error: true` in the GitHub actions config 🤦
3
11
  - Docker builds would fail if no previous images existed in the registry.
data/lib/kuby/commands.rb CHANGED
@@ -62,12 +62,22 @@ module Kuby
62
62
  true
63
63
  end
64
64
 
65
- desc 'Builds the Docker image.'
65
+ desc 'Builds Docker images.'
66
66
  command :build do |c|
67
+ c.desc 'Docker build argument.'
67
68
  c.flag [:a, :arg], required: false, multiple: true
69
+
70
+ c.desc 'When enabled, ignores missing build arguments.'
68
71
  c.switch [:'ignore-missing-args'], required: false, default: false
69
- c.flag [:only], required: false
72
+
73
+ c.desc 'Build only the images associated with the specified identifier(s). '\
74
+ 'Run `kuby images` for a list of all valid identifiers (note that '\
75
+ 'identifiers can be associated with more than one image).'
76
+ c.flag [:only], required: false, multiple: true
77
+
78
+ c.desc 'The directory to use as the Docker build context.'
70
79
  c.flag [:c, :context], required: false
80
+
71
81
  c.action do |global_options, options, docker_args|
72
82
  build_args = {}.tap do |build_args|
73
83
  (options[:arg] || []).each do |a|
@@ -86,9 +96,12 @@ module Kuby
86
96
  end
87
97
  end
88
98
 
89
- desc 'Pushes the Docker image to the configured registry.'
99
+ desc 'Pushes Docker images to their associated registries.'
90
100
  command :push do |c|
91
- c.flag [:only], required: false
101
+ c.desc 'Push only the images associated with the specified identifier(s). '\
102
+ 'Run `kuby images` for a list of all valid identifiers (note that '\
103
+ 'identifiers can be associated with more than one image).'
104
+ c.flag [:only], required: false, multiple: true
92
105
  c.action do |global_options, options, args|
93
106
  tasks.push(only: options[:only])
94
107
  end
@@ -96,14 +109,18 @@ module Kuby
96
109
 
97
110
  desc 'Gets your Kubernetes cluster ready to run your Rails app.'
98
111
  command :setup do |c|
112
+ c.desc 'Run the setup routines for only the specified plugin identifier(s).'
113
+ c.flag [:only], required: false, multiple: true
99
114
  c.action do |global_options, options, args|
100
- tasks.setup
115
+ tasks.setup(only: options[:only])
101
116
  end
102
117
  end
103
118
 
104
119
  desc 'Prints the effective Dockerfiles used to build Docker images.'
105
120
  command :dockerfiles do |c|
106
- c.flag [:only], required: false
121
+ c.desc 'Print Dockerfiles for only the images associated with the specified '\
122
+ 'identifier(s).'
123
+ c.flag [:only], required: false, multiple: true
107
124
  c.action do |global_options, options, args|
108
125
  tasks.print_dockerfiles(only: options[:only])
109
126
  end
@@ -118,7 +135,7 @@ module Kuby
118
135
  end
119
136
  end
120
137
 
121
- desc 'Rolls back to the previous Docker tag.'
138
+ desc 'Rolls back to the previous release.'
122
139
  command :rollback do |c|
123
140
  c.action do |global_options, options, args|
124
141
  tasks.rollback
@@ -127,25 +144,37 @@ module Kuby
127
144
 
128
145
  desc 'Prints the effective Kubernetes resources that will be applied on deploy.'
129
146
  command :resources do |c|
147
+ c.desc 'Only print resources of the given kind.'
130
148
  c.flag [:K, :kind], required: false
149
+
150
+ c.desc 'Only print resources that match the given name.'
131
151
  c.flag [:N, :name], required: false
152
+
132
153
  c.action do |global_options, options, args|
133
154
  tasks.print_resources(options[:kind], options[:name])
134
155
  end
135
156
  end
136
157
 
137
- desc 'Prints out the contents of the kubeconfig Kuby is using to communicate with your cluster.'
158
+ desc 'Prints out the contents of the kubeconfig file Kuby is using to communicate '\
159
+ 'with your cluster.'
138
160
  command :kubeconfig do |c|
139
161
  c.action do |global_options, options, args|
140
162
  tasks.print_kubeconfig
141
163
  end
142
164
  end
143
165
 
166
+ desc 'Prints out the URLs to the latest Docker images in the Docker registry.'
167
+ command :images do |c|
168
+ c.action do |global_options, options, args|
169
+ tasks.print_images
170
+ end
171
+ end
172
+
144
173
  desc 'Runs an arbitrary kubectl command.'
145
174
  command :kubectl do |c|
146
175
  c.desc 'Prefixes the kubectl command with the namespace associated with '\
147
- 'the current environment. For example, if the Kuby env is "production", '\
148
- 'this option will prefix the kubectl command with "-n myapp-production".'
176
+ 'the current environment. For example, if the Kuby env is "production", '\
177
+ 'this option will prefix the kubectl command with "-n myapp-production".'
149
178
  c.switch [:N, :namespaced], default: false
150
179
  c.action do |global_options, options, args|
151
180
  if options[:namespaced]
@@ -79,8 +79,6 @@ module Kuby
79
79
  sig { params(build_args: T::Hash[String, String], docker_args: T::Array[String], context: T.nilable(String)).void }
80
80
  def build(build_args = {}, docker_args = [], context: nil)
81
81
  docker_cli.build(new_version, build_args: build_args, docker_args: docker_args, context: context)
82
- @current_version = new_version
83
- @new_version = nil
84
82
  end
85
83
 
86
84
  sig { params(tag: String).void }
@@ -7,12 +7,13 @@ module Kuby
7
7
  class BareMetalProvider < Provider
8
8
  extend T::Sig
9
9
 
10
- STORAGE_CLASS_NAME = T.let('hostpath'.freeze, String)
10
+ DEFAULT_STORAGE_CLASS = T.let('hostpath'.freeze, String)
11
11
 
12
12
  class Config
13
13
  extend ::KubeDSL::ValueFields
14
14
 
15
15
  value_fields :kubeconfig
16
+ value_fields :storage_class
16
17
  end
17
18
 
18
19
  sig { returns(Config) }
@@ -36,7 +37,7 @@ module Kuby
36
37
 
37
38
  sig { returns(String) }
38
39
  def storage_class_name
39
- STORAGE_CLASS_NAME
40
+ config.storage_class
40
41
  end
41
42
 
42
43
  private
@@ -46,6 +47,7 @@ module Kuby
46
47
  configure do
47
48
  # default kubeconfig path
48
49
  kubeconfig File.join(ENV['HOME'], '.kube', 'config')
50
+ storage_class DEFAULT_STORAGE_CLASS
49
51
  end
50
52
  end
51
53
  end
@@ -89,13 +89,23 @@ module Kuby
89
89
  @tag = nil
90
90
  end
91
91
 
92
- def setup
93
- provider.before_setup
94
- provider.setup
92
+ def setup(only: [])
93
+ plugins = if only.empty?
94
+ @plugins
95
+ else
96
+ @plugins.each_with_object({}) do |(name, plg), memo|
97
+ memo[name] = plg if only.include?(name)
98
+ end
99
+ end
100
+
101
+ if only.empty?
102
+ provider.before_setup
103
+ provider.setup
104
+ end
95
105
 
96
- @plugins.each { |_, plg| plg.before_setup }
97
- @plugins.each { |_, plg| plg.setup }
98
- @plugins.each { |_, plg| plg.after_setup }
106
+ plugins.each { |_, plg| plg.before_setup }
107
+ plugins.each { |_, plg| plg.setup }
108
+ plugins.each { |_, plg| plg.after_setup }
99
109
 
100
110
  provider.after_setup
101
111
  end
data/lib/kuby/plugin.rb CHANGED
@@ -12,6 +12,7 @@ module Kuby
12
12
  # do nothing by default
13
13
  end
14
14
 
15
+ # install any global resources like operators, etc
15
16
  def setup
16
17
  # do nothing by default
17
18
  end
@@ -1,6 +1,8 @@
1
1
  # typed: false
2
2
  module Kuby
3
3
  class PluginRegistry
4
+ include Enumerable
5
+
4
6
  ANY = 'any'.freeze
5
7
 
6
8
  def register(plugin_name, plugin_klass, environment: ANY)
@@ -19,6 +21,19 @@ module Kuby
19
21
  plugins_by_env[environment] || plugins_by_env[ANY]
20
22
  end
21
23
 
24
+ def each(&block)
25
+ return to_enum(__method__) unless block
26
+
27
+ @plugins.each_pair do |plugin_name, plugins_by_env|
28
+ plugins_by_env.each_pair do |env, plugin_klass|
29
+ case env
30
+ when ANY, Kuby.env
31
+ yield plugin_name, plugin_klass
32
+ end
33
+ end
34
+ end
35
+ end
36
+
22
37
  private
23
38
 
24
39
  def plugins
@@ -11,9 +11,11 @@ module Kuby
11
11
  end
12
12
 
13
13
  def new_version
14
- # Asset images track the base image, so return the current version
14
+ # Asset images track the base image, so return the new version
15
15
  # here. There can be no asset image without a base image.
16
- current_version
16
+ @new_version ||= duplicate_with_annotated_tags(
17
+ base_image.new_version
18
+ )
17
19
  end
18
20
 
19
21
  def current_version
@@ -29,7 +31,7 @@ module Kuby
29
31
  end
30
32
 
31
33
  def build(build_args = {}, docker_args = [], context: nil)
32
- docker_cli.build(current_version, build_args: build_args, docker_args: docker_args, context: context)
34
+ docker_cli.build(new_version, build_args: build_args, docker_args: docker_args, context: context)
33
35
  end
34
36
 
35
37
  def push(tag)
@@ -209,15 +209,7 @@ module Kuby
209
209
  type 'Opaque'
210
210
 
211
211
  data do
212
- if master_key = ENV[MASTER_KEY_VAR]
213
- add MASTER_KEY_VAR.to_sym, master_key
214
- else
215
- master_key_path = File.join(spec.root, 'config', 'master.key')
216
-
217
- if File.exist?(master_key_path)
218
- add MASTER_KEY_VAR.to_sym, File.read(master_key_path).strip
219
- end
220
- end
212
+ add MASTER_KEY_VAR.to_sym, spec.master_key
221
213
  end
222
214
  end
223
215
 
@@ -434,6 +426,13 @@ module Kuby
434
426
  def namespace
435
427
  environment.kubernetes.namespace
436
428
  end
429
+
430
+ def master_key
431
+ @master_key ||= ENV[MASTER_KEY_VAR] || begin
432
+ master_key_path = File.join(root, 'config', 'master.key')
433
+ File.read(master_key_path).strip if File.exist?(master_key_path)
434
+ end
435
+ end
437
436
  end
438
437
  end
439
438
  end
data/lib/kuby/tasks.rb CHANGED
@@ -24,23 +24,19 @@ module Kuby
24
24
  end
25
25
  end
26
26
 
27
- def setup
28
- environment.kubernetes.setup
27
+ def setup(only: [])
28
+ environment.kubernetes.setup(only: only.map(&:to_sym))
29
29
  end
30
30
 
31
- def build(build_args = {}, docker_args = [], only: nil, ignore_missing_args: false, context: nil)
31
+ def build(build_args = {}, docker_args = [], only: [], ignore_missing_args: false, context: nil)
32
32
  check_platform(docker_args)
33
33
 
34
- build_args['RAILS_MASTER_KEY'] ||= ENV['RAILS_MASTER_KEY'] || begin
35
- master_key_file = File.join('config', 'master.key')
36
- File.exist?(master_key_file) ? File.read(master_key_file).strip : nil
37
- end
34
+ build_args['RAILS_MASTER_KEY'] ||= rails_app.master_key
38
35
 
39
36
  check_build_args(build_args) unless ignore_missing_args
40
37
 
41
38
  kubernetes.docker_images.each do |image|
42
- next if only && image.identifier != only
43
-
39
+ next unless only.empty? || only.include?(image.identifier)
44
40
  return unless perform_docker_login_if_necessary(image)
45
41
 
46
42
  image = image.new_version
@@ -49,9 +45,9 @@ module Kuby
49
45
  end
50
46
  end
51
47
 
52
- def push(only: nil)
48
+ def push(only: [])
53
49
  kubernetes.docker_images.each do |image|
54
- next if only && image.identifier != only
50
+ next unless only.empty? || only.include?(image.identifier)
55
51
 
56
52
  image = image.current_version
57
53
  Kuby.logger.info("Pushing image #{image.image_url} with tags #{image.tags.join(', ')}")
@@ -101,6 +97,18 @@ module Kuby
101
97
  puts File.read(path)
102
98
  end
103
99
 
100
+ def print_images
101
+ rows = kubernetes.docker_images.flat_map do |image|
102
+ image = image.current_version
103
+
104
+ image.tags.map do |tag|
105
+ [image.identifier, "#{image.image_url}:#{tag}"]
106
+ end
107
+ end
108
+
109
+ puts Kuby::Utils::Table.new(%w(IDENTIFIER URL), rows).to_s
110
+ end
111
+
104
112
  def kubectl(*cmd)
105
113
  kubernetes_cli.run_cmd(cmd)
106
114
  end
@@ -0,0 +1,35 @@
1
+ module Kuby
2
+ module Utils
3
+ class Table
4
+ attr_reader :headers, :rows
5
+
6
+ def initialize(headers, rows)
7
+ @headers = headers
8
+ @rows = rows
9
+ end
10
+
11
+ def to_s
12
+ [headers, *rows].map { |vals| make_row(vals) }.join("\n")
13
+ end
14
+
15
+ private
16
+
17
+ def make_row(values)
18
+ columns = values.each_with_index.map do |value, idx|
19
+ col_width = col_width_at(idx) + 2
20
+ value.ljust(col_width, ' ')
21
+ end
22
+
23
+ columns.join
24
+ end
25
+
26
+ def col_width_at(idx)
27
+ col_widths[idx] ||= [headers[idx].size, *rows.map { |r| r[idx].size }].max
28
+ end
29
+
30
+ def col_widths
31
+ @col_widths ||= {}
32
+ end
33
+ end
34
+ end
35
+ end
data/lib/kuby/utils.rb ADDED
@@ -0,0 +1,5 @@
1
+ module Kuby
2
+ module Utils
3
+ autoload :Table, 'kuby/utils/table'
4
+ end
5
+ end
data/lib/kuby/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # typed: true
2
2
 
3
3
  module Kuby
4
- VERSION = '0.16.1'.freeze
4
+ VERSION = '0.17.0'.freeze
5
5
  end
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.16.1
4
+ version: 0.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cameron Dutro
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-05 00:00:00.000000000 Z
11
+ date: 2022-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -285,6 +285,8 @@ files:
285
285
  - lib/kuby/railtie.rb
286
286
  - lib/kuby/tasks.rb
287
287
  - lib/kuby/trailing_hash.rb
288
+ - lib/kuby/utils.rb
289
+ - lib/kuby/utils/table.rb
288
290
  - lib/kuby/version.rb
289
291
  - spec/docker/spec_spec.rb
290
292
  - spec/docker/timestamp_tag_spec.rb