kuby-core 0.17.0 → 0.18.0

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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -0
  3. data/Gemfile +6 -2
  4. data/Rakefile +5 -3
  5. data/bin/tapioca +29 -0
  6. data/kuby-core.gemspec +9 -11
  7. data/lib/kuby/basic_logger.rb +34 -34
  8. data/lib/kuby/cli_base.rb +43 -43
  9. data/lib/kuby/commands.rb +94 -11
  10. data/lib/kuby/definition.rb +12 -12
  11. data/lib/kuby/dependable.rb +20 -0
  12. data/lib/kuby/dependency.rb +14 -0
  13. data/lib/kuby/docker/alpine.rb +10 -10
  14. data/lib/kuby/docker/app_image.rb +11 -11
  15. data/lib/kuby/docker/app_phase.rb +36 -0
  16. data/lib/kuby/docker/assets_phase.rb +2 -2
  17. data/lib/kuby/docker/bundler_phase.rb +42 -40
  18. data/lib/kuby/docker/cli.rb +71 -43
  19. data/lib/kuby/docker/copy_phase.rb +7 -7
  20. data/lib/kuby/docker/credentials.rb +1 -0
  21. data/lib/kuby/docker/debian.rb +10 -10
  22. data/lib/kuby/docker/distro.rb +13 -13
  23. data/lib/kuby/docker/docker_uri.rb +20 -20
  24. data/lib/kuby/docker/dockerfile.rb +48 -39
  25. data/lib/kuby/docker/image.rb +66 -54
  26. data/lib/kuby/docker/inline_layer.rb +4 -4
  27. data/lib/kuby/docker/layer.rb +6 -6
  28. data/lib/kuby/docker/layer_stack.rb +35 -35
  29. data/lib/kuby/docker/local_tags.rb +16 -16
  30. data/lib/kuby/docker/package_list.rb +16 -16
  31. data/lib/kuby/docker/package_phase.rb +16 -16
  32. data/lib/kuby/docker/packages/managed_package.rb +13 -13
  33. data/lib/kuby/docker/packages/nodejs.rb +5 -5
  34. data/lib/kuby/docker/packages/package.rb +8 -8
  35. data/lib/kuby/docker/packages/simple_managed_package.rb +7 -7
  36. data/lib/kuby/docker/packages/yarn.rb +6 -6
  37. data/lib/kuby/docker/remote_tags.rb +16 -16
  38. data/lib/kuby/docker/setup_phase.rb +18 -20
  39. data/lib/kuby/docker/spec.rb +93 -72
  40. data/lib/kuby/docker/timestamp_tag.rb +16 -11
  41. data/lib/kuby/docker/timestamped_image.rb +59 -40
  42. data/lib/kuby/docker/webserver_phase.rb +20 -20
  43. data/lib/kuby/docker/yarn_phase.rb +29 -5
  44. data/lib/kuby/docker.rb +2 -1
  45. data/lib/kuby/kubernetes/bare_metal_provider.rb +9 -9
  46. data/lib/kuby/kubernetes/deployer.rb +22 -10
  47. data/lib/kuby/kubernetes/docker_config.rb +1 -0
  48. data/lib/kuby/kubernetes/provider.rb +1 -0
  49. data/lib/kuby/kubernetes/spec.rb +47 -7
  50. data/lib/kuby/plugin.rb +22 -1
  51. data/lib/kuby/plugins/nginx_ingress.rb +8 -6
  52. data/lib/kuby/plugins/rails_app/assets.rb +16 -4
  53. data/lib/kuby/plugins/rails_app/assets_image.rb +17 -8
  54. data/lib/kuby/plugins/rails_app/crdb/plugin.rb +473 -0
  55. data/lib/kuby/plugins/rails_app/crdb.rb +9 -0
  56. data/lib/kuby/plugins/rails_app/database.rb +12 -8
  57. data/lib/kuby/plugins/rails_app/generators/kuby.rb +17 -16
  58. data/lib/kuby/plugins/rails_app/plugin.rb +29 -18
  59. data/lib/kuby/plugins/rails_app/sqlite.rb +7 -3
  60. data/lib/kuby/plugins/rails_app/tasks.rake +25 -12
  61. data/lib/kuby/plugins/rails_app.rb +1 -0
  62. data/lib/kuby/plugins/system.rb +16 -0
  63. data/lib/kuby/plugins.rb +1 -0
  64. data/lib/kuby/railtie.rb +31 -1
  65. data/lib/kuby/tasks.rb +72 -5
  66. data/lib/kuby/trailing_hash.rb +2 -2
  67. data/lib/kuby/utils/sem_ver/constraint.rb +68 -0
  68. data/lib/kuby/utils/sem_ver/constraint_set.rb +25 -0
  69. data/lib/kuby/utils/sem_ver/version.rb +49 -0
  70. data/lib/kuby/utils/sem_ver.rb +17 -0
  71. data/lib/kuby/utils/which.rb +65 -0
  72. data/lib/kuby/utils.rb +7 -1
  73. data/lib/kuby/version.rb +1 -1
  74. data/lib/kuby.rb +37 -2
  75. data/rbi/kuby-core.rbi +2128 -0
  76. data/spec/docker/spec_spec.rb +50 -26
  77. data/spec/dummy/app/channels/application_cable/channel.rb +2 -1
  78. data/spec/dummy/app/channels/application_cable/connection.rb +2 -1
  79. data/spec/dummy/app/controllers/application_controller.rb +2 -1
  80. data/spec/dummy/app/jobs/application_job.rb +2 -1
  81. data/spec/dummy/app/mailers/application_mailer.rb +2 -1
  82. data/spec/dummy/app/models/application_record.rb +2 -1
  83. data/spec/dummy/config/application.rb +2 -1
  84. data/spec/dummy/config/initializers/wrap_parameters.rb +2 -1
  85. data/spec/dummy/config/routes.rb +2 -1
  86. data/spec/dummy/test/application_system_test_case.rb +2 -1
  87. data/spec/dummy/test/channels/application_cable/connection_test.rb +2 -1
  88. data/spec/spec_helper.rb +13 -1
  89. metadata +44 -39
  90. data/lib/kuby/plugins/rails_app/mysql.rb +0 -158
  91. data/lib/kuby/plugins/rails_app/postgres.rb +0 -163
@@ -6,7 +6,7 @@ module Kuby
6
6
  class Sqlite < ::Kuby::Plugin
7
7
  attr_reader :environment
8
8
 
9
- def initialize(environment, *)
9
+ def initialize(environment, *_)
10
10
  @environment = environment
11
11
  end
12
12
 
@@ -15,8 +15,12 @@ module Kuby
15
15
  environment.docker.package_phase.add(:sqlite_client)
16
16
  end
17
17
 
18
- def requires_credentials?
19
- false
18
+ def configure_pod_spec(_pod_spec)
19
+ # no configuration steps necessary
20
+ end
21
+
22
+ def bootstrap
23
+ # no boostrap steps necessary
20
24
  end
21
25
 
22
26
  def user(_user)
@@ -7,29 +7,42 @@ namespace :kuby do
7
7
  Kuby.load!
8
8
 
9
9
  config_file = File.join(Kuby.environment.kubernetes.plugin(:rails_app).root, 'config', 'database.yml')
10
- database = Kuby.environment.kubernetes.plugin(:rails_app).database
11
10
 
12
- if database.plugin.respond_to?(:rewritten_configs)
13
- File.write(config_file, YAML.dump(database.plugin.rewritten_configs))
14
- Kuby.logger.info("Wrote #{config_file}")
11
+ if rails_app = Kuby.environment.kubernetes.plugin(:rails_app)
12
+ database = rails_app.database
13
+
14
+ if database.plugin.respond_to?(:rewritten_configs)
15
+ File.write(config_file, YAML.dump(database.plugin.rewritten_configs))
16
+ Kuby.logger.info("Wrote #{config_file}")
17
+ end
15
18
  end
16
19
  end
17
20
 
18
- task :create_unless_exists do
19
- begin
20
- Rake::Task['environment'].invoke
21
- ActiveRecord::Base.connection
22
- rescue ActiveRecord::NoDatabaseError => e
23
- Rake::Task['db:create'].invoke
21
+ task :bootstrap do
22
+ Kuby.load!
23
+
24
+ if rails_app = Kuby.environment.kubernetes.plugin(:rails_app)
25
+ if database = rails_app.database
26
+ database.plugin.bootstrap
27
+ end
24
28
  end
25
29
  end
30
+
31
+ task :migrate do
32
+ next unless Kernel.const_defined?('::ActiveRecord')
33
+
34
+ Rake::Task['environment'].invoke
35
+ Rake::Task['db:migrate'].invoke
36
+ end
26
37
  end
27
38
 
28
39
  namespace :assets do
29
40
  task :copy do
30
41
  Kuby.load!
31
- assets = Kuby.environment.kubernetes.plugin(:rails_assets)
32
- assets.copy_task.run
42
+
43
+ if assets = Kuby.environment.kubernetes.plugin(:rails_assets)
44
+ assets.copy_task.run
45
+ end
33
46
  end
34
47
  end
35
48
  end
@@ -5,6 +5,7 @@ module Kuby
5
5
  autoload :AssetCopyTask, 'kuby/plugins/rails_app/asset_copy_task'
6
6
  autoload :AssetsImage, 'kuby/plugins/rails_app/assets_image'
7
7
  autoload :Assets, 'kuby/plugins/rails_app/assets'
8
+ autoload :CRDB, 'kuby/plugins/rails_app/crdb'
8
9
  autoload :Database, 'kuby/plugins/rails_app/database'
9
10
  autoload :MySQL, 'kuby/plugins/rails_app/mysql'
10
11
  autoload :Plugin, 'kuby/plugins/rails_app/plugin'
@@ -0,0 +1,16 @@
1
+ # typed: true
2
+
3
+ require 'kube-dsl'
4
+
5
+ module Kuby
6
+ module Plugins
7
+ class System < ::Kuby::Plugin
8
+ # Kubernetes maintains backwards compatibility for the three most recent
9
+ # minor versions. In other words, everything that works in v1.23 also works
10
+ # in v1.22 and v1.21. Kuby tries to do the same. As of the time of this
11
+ # writing, the most recent k8s release is v1.23, so Kuby supports v1.21 and up.
12
+ depends_on :kubernetes, '~> 1.21'
13
+ depends_on :kubectl, '~> 1.21'
14
+ end
15
+ end
16
+ end
data/lib/kuby/plugins.rb CHANGED
@@ -3,5 +3,6 @@ module Kuby
3
3
  module Plugins
4
4
  autoload :NginxIngress, 'kuby/plugins/nginx_ingress'
5
5
  autoload :RailsApp, 'kuby/plugins/rails_app'
6
+ autoload :System, 'kuby/plugins/system'
6
7
  end
7
8
  end
data/lib/kuby/railtie.rb CHANGED
@@ -1,11 +1,41 @@
1
- # typed: strict
1
+ # typed: ignore
2
+
2
3
  require 'logger'
3
4
  require 'rails/railtie'
5
+ require 'rails/command'
6
+ require 'rails/commands/dbconsole/dbconsole_command'
4
7
 
5
8
  module Kuby
9
+ module CockroachConsoleMonkeypatch
10
+ def start
11
+ config_hash = if respond_to?(:config)
12
+ config_hash = config
13
+ else
14
+ config_hash = db_config.configuration_hash.stringify_keys
15
+ end
16
+
17
+ return super unless config_hash['adapter'] == 'cockroachdb'
18
+
19
+ ENV['PGUSER'] = config_hash['username'] if config_hash['username']
20
+ ENV['PGHOST'] = config_hash['host'] if config_hash['host']
21
+ ENV['PGPORT'] = config_hash['port'].to_s if config_hash['port']
22
+ ENV['PGPASSWORD'] = config_hash['password'].to_s if config_hash['password'] && @options['include_password']
23
+ ENV['PGSSLMODE'] = config_hash['sslmode'].to_s if config_hash['sslmode']
24
+ ENV['PGSSLCERT'] = config_hash['sslcert'].to_s if config_hash['sslcert']
25
+ ENV['PGSSLKEY'] = config_hash['sslkey'].to_s if config_hash['sslkey']
26
+ ENV['PGSSLROOTCERT'] = config_hash['sslrootcert'].to_s if config_hash['sslrootcert']
27
+
28
+ find_cmd_and_exec('psql', config_hash['database'])
29
+ end
30
+ end
31
+
6
32
  class Railtie < ::Rails::Railtie
7
33
  initializer 'kuby.health_check_middleware' do |app|
8
34
  app.middleware.use Kuby::Middleware::HealthCheck
9
35
  end
36
+
37
+ initializer 'kuby.cockroachdb_console_support' do
38
+ Rails::DBConsole.prepend(CockroachConsoleMonkeypatch)
39
+ end
10
40
  end
11
41
  end
data/lib/kuby/tasks.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # typed: false
2
+ require 'rake'
2
3
  require 'rouge'
3
4
 
4
5
  module Kuby
@@ -9,9 +10,9 @@ module Kuby
9
10
  @environment = environment
10
11
  end
11
12
 
12
- def print_dockerfiles(only: nil)
13
+ def print_dockerfiles(only: [])
13
14
  kubernetes.docker_images.each do |image|
14
- next if only && image.identifier != only
15
+ next unless only.empty? || only.include?(image.identifier)
15
16
 
16
17
  image = image.current_version
17
18
  identifier = image.identifier ? " ##{image.identifier}" : ""
@@ -28,10 +29,63 @@ module Kuby
28
29
  environment.kubernetes.setup(only: only.map(&:to_sym))
29
30
  end
30
31
 
31
- def build(build_args = {}, docker_args = [], only: [], ignore_missing_args: false, context: nil)
32
+ def remove_plugin(name)
33
+ plugin = environment.kubernetes.plugin(name)
34
+
35
+ # Allow running uninstallation procedures for plugins that are no longer part
36
+ # of the environment. This is especially useful for plugins Kuby adds by default
37
+ # in one version and removes in another, like KubeDB.
38
+ plugin ||= if plugin_class = Kuby.plugins.find(name.to_sym)
39
+ plugin_class.new(environment)
40
+ end
41
+
42
+ unless plugin
43
+ Kuby.logger.fatal(
44
+ "No plugin found named '#{name}'. Run `kuby plugin list -a` to show a list of all available plugins."
45
+ )
46
+
47
+ exit 1
48
+ end
49
+
50
+ plugin.remove
51
+ end
52
+
53
+ def list_plugins(all: false)
54
+ Kuby.plugins.each do |name, _|
55
+ if environment.kubernetes.plugins.include?(name)
56
+ Kuby.logger.info("* #{name}")
57
+ elsif all
58
+ Kuby.logger.info(" #{name}")
59
+ end
60
+ end
61
+ end
62
+
63
+ def run_rake_tasks(tasks)
64
+ if tasks.empty?
65
+ Kuby.logger.fatal('Please specify at least one task to run.')
66
+ exit 1
67
+ end
68
+
69
+ Kuby.load_rake_tasks!
70
+ Rake::Task[tasks.join(' ')].invoke
71
+ end
72
+
73
+ def list_rake_tasks
74
+ Kuby.load_rake_tasks!
75
+
76
+ rows = Rake::Task.tasks.map do |task|
77
+ [task.name, task.full_comment || '']
78
+ end
79
+
80
+ puts Kuby::Utils::Table.new(%w(NAME DESCRIPTION), rows).to_s
81
+ end
82
+
83
+ def build(build_args = {}, docker_args = [], only: [], ignore_missing_args: false, context: nil, cache_from_latest: true)
32
84
  check_platform(docker_args)
33
85
 
34
- build_args['RAILS_MASTER_KEY'] ||= rails_app.master_key
86
+ if master_key = rails_app.master_key
87
+ build_args['RAILS_MASTER_KEY'] = master_key
88
+ end
35
89
 
36
90
  check_build_args(build_args) unless ignore_missing_args
37
91
 
@@ -39,9 +93,22 @@ module Kuby
39
93
  next unless only.empty? || only.include?(image.identifier)
40
94
  return unless perform_docker_login_if_necessary(image)
41
95
 
96
+ build_kwargs = {}
97
+
98
+ if cache_from_latest
99
+ latest_image_url = "#{image.image_url}:#{Kuby::Docker::LATEST_TAG}"
100
+ Kuby.logger.info("Pulling image #{latest_image_url}")
101
+
102
+ begin
103
+ image.pull(Kuby::Docker::LATEST_TAG)
104
+ build_kwargs[:cache_from] = latest_image_url
105
+ rescue Kuby::Docker::PullError
106
+ end
107
+ end
108
+
42
109
  image = image.new_version
43
110
  Kuby.logger.info("Building image #{image.image_url} with tags #{image.tags.join(', ')}")
44
- image.build(build_args, docker_args, context: context)
111
+ image.build(build_args, docker_args, context: context, **build_kwargs)
45
112
  end
46
113
  end
47
114
 
@@ -3,14 +3,14 @@
3
3
  module Kuby
4
4
  class TrailingHash < Hash
5
5
  def each(&block)
6
- return to_enum(T.must(__method__)) unless block_given?
6
+ return to_enum(__method__) unless block_given?
7
7
 
8
8
  seen_keys = []
9
9
  keys_before = keys
10
10
 
11
11
  until keys_before.empty?
12
12
  keys_before.each do |k|
13
- yield k, T.must(self[k])
13
+ yield k, self[k]
14
14
  seen_keys << k
15
15
  end
16
16
 
@@ -0,0 +1,68 @@
1
+ module Kuby
2
+ module Utils
3
+ module SemVer
4
+ class Constraint
5
+ OPERATOR_MAP = {
6
+ '=' => :eq,
7
+ '>' => :gt,
8
+ '>=' => :gteq,
9
+ '<' => :lt,
10
+ '<=' => :lteq,
11
+ '~>' => :waka
12
+ }
13
+
14
+ OPERATOR_MAP.freeze
15
+
16
+ OPERATOR_INVERSE = OPERATOR_MAP.invert.freeze
17
+
18
+ attr_reader :operator, :version
19
+
20
+ def self.parse(str)
21
+ op, ver = str.split(' ')
22
+ new(OPERATOR_MAP.fetch(op), Version.parse(ver, default: nil))
23
+ end
24
+
25
+ def initialize(operator, version)
26
+ @operator = operator
27
+ @version = version
28
+ end
29
+
30
+ def to_s
31
+ @str ||= "#{OPERATOR_INVERSE[operator]} #{version}"
32
+ end
33
+
34
+ def satisfied_by?(other_version)
35
+ case operator
36
+ when :waka
37
+ arr = version.to_a
38
+ other_arr = other_version.to_a
39
+
40
+ arr.each_with_index do |digit, idx|
41
+ break unless digit
42
+
43
+ next_digit = arr[idx + 1]
44
+
45
+ if next_digit
46
+ return false if other_arr[idx] != digit
47
+ else
48
+ return false if other_arr[idx] < digit
49
+ end
50
+ end
51
+
52
+ true
53
+ when :eq
54
+ other_version == version
55
+ when :gt
56
+ other_version > version
57
+ when :gteq
58
+ other_version >= version
59
+ when :lt
60
+ other_version < version
61
+ when :lteq
62
+ other_version <= version
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,25 @@
1
+ module Kuby
2
+ module Utils
3
+ module SemVer
4
+ class ConstraintSet
5
+ attr_reader :constraints
6
+
7
+ def self.parse(*arr)
8
+ new(arr.map { |c| Constraint.parse(c) })
9
+ end
10
+
11
+ def initialize(constraints)
12
+ @constraints = constraints
13
+ end
14
+
15
+ def satisfied_by?(version)
16
+ constraints.all? { |c| c.satisfied_by?(version) }
17
+ end
18
+
19
+ def to_s
20
+ @str ||= constraints.map(&:to_s).join(', ')
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,49 @@
1
+ module Kuby
2
+ module Utils
3
+ module SemVer
4
+ class Version
5
+ include Comparable
6
+
7
+ attr_reader :major, :minor, :patch
8
+
9
+ def self.parse(str, default: 0)
10
+ major, minor, patch = str.split('.')
11
+
12
+ new(
13
+ major ? major.to_i : default,
14
+ minor ? minor.to_i : default,
15
+ patch ? patch.to_i : default
16
+ )
17
+ end
18
+
19
+ def initialize(major, minor, patch)
20
+ @major = major
21
+ @minor = minor
22
+ @patch = patch
23
+ end
24
+
25
+ def to_s
26
+ @str ||= [major, minor, patch].compact.join('.')
27
+ end
28
+
29
+ def to_a
30
+ @arr ||= [major, minor, patch]
31
+ end
32
+
33
+ def <=>(other)
34
+ other_arr = other.to_a
35
+
36
+ to_a.each_with_index do |digit, idx|
37
+ other_digit = other_arr[idx] || 0
38
+
39
+ if digit != other_digit
40
+ return digit <=> other_digit
41
+ end
42
+ end
43
+
44
+ 0
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,17 @@
1
+ module Kuby
2
+ module Utils
3
+ module SemVer
4
+ autoload :Constraint, 'kuby/utils/sem_ver/constraint'
5
+ autoload :ConstraintSet, 'kuby/utils/sem_ver/constraint_set'
6
+ autoload :Version, 'kuby/utils/sem_ver/version'
7
+
8
+ def self.parse_version(str)
9
+ Version.parse(str)
10
+ end
11
+
12
+ def self.parse_constraints(*strs)
13
+ ConstraintSet.parse(*strs)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,65 @@
1
+ module Kuby
2
+ module Utils
3
+ # This code was copied from the ptools gem, licensed under the Artistic v2 license:
4
+ # https://github.com/djberg96/ptools/blob/4ef26adc870cf02b8342df58da53c61bcd4af6c4/lib/ptools.rb
5
+ #
6
+ # Only the #which function and dependent constants have been copied. None of the copied code
7
+ # has been modified.
8
+ #
9
+ module Which
10
+ if File::ALT_SEPARATOR
11
+ MSWINDOWS = true
12
+ if ENV['PATHEXT']
13
+ WIN32EXTS = ".{#{ENV['PATHEXT'].tr(';', ',').tr('.', '')}}".downcase
14
+ else
15
+ WIN32EXTS = '.{exe,com,bat}'.freeze
16
+ end
17
+ else
18
+ MSWINDOWS = false
19
+ end
20
+
21
+ def which(program, path = ENV['PATH'])
22
+ raise ArgumentError, 'path cannot be empty' if path.nil? || path.empty?
23
+
24
+ # Bail out early if an absolute path is provided.
25
+ if program =~ /^\/|^[a-z]:[\\\/]/i
26
+ program += WIN32EXTS if MSWINDOWS && File.extname(program).empty?
27
+ found = Dir[program].first
28
+ if found && File.executable?(found) && !File.directory?(found)
29
+ return found
30
+ else
31
+ return nil
32
+ end
33
+ end
34
+
35
+ # Iterate over each path glob the dir + program.
36
+ path.split(File::PATH_SEPARATOR).each do |dir|
37
+ dir = File.expand_path(dir)
38
+
39
+ next unless File.exist?(dir) # In case of bogus second argument
40
+
41
+ file = File.join(dir, program)
42
+
43
+ # Dir[] doesn't handle backslashes properly, so convert them. Also, if
44
+ # the program name doesn't have an extension, try them all.
45
+ if MSWINDOWS
46
+ file = file.tr(File::ALT_SEPARATOR, File::SEPARATOR)
47
+ file += WIN32EXTS if File.extname(program).empty?
48
+ end
49
+
50
+ found = Dir[file].first
51
+
52
+ # Convert all forward slashes to backslashes if supported
53
+ if found && File.executable?(found) && !File.directory?(found)
54
+ found.tr!(File::SEPARATOR, File::ALT_SEPARATOR) if File::ALT_SEPARATOR
55
+ return found
56
+ end
57
+ end
58
+
59
+ nil
60
+ end
61
+
62
+ extend(self)
63
+ end
64
+ end
65
+ end
data/lib/kuby/utils.rb CHANGED
@@ -1,5 +1,11 @@
1
1
  module Kuby
2
2
  module Utils
3
- autoload :Table, 'kuby/utils/table'
3
+ autoload :SemVer, 'kuby/utils/sem_ver'
4
+ autoload :Table, 'kuby/utils/table'
5
+ autoload :Which, 'kuby/utils/which'
6
+
7
+ def self.which(*args)
8
+ Which.which(*args)
9
+ end
4
10
  end
5
11
  end
data/lib/kuby/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # typed: true
2
2
 
3
3
  module Kuby
4
- VERSION = '0.17.0'.freeze
4
+ VERSION = '0.18.0'.freeze
5
5
  end
data/lib/kuby.rb CHANGED
@@ -1,7 +1,9 @@
1
- # typed: false
1
+ # typed: ignore
2
2
 
3
- require 'sorbet-runtime-stub'
4
3
  require 'kuby/railtie'
4
+ require 'kubectl-rb/version'
5
+ require 'helm-rb/version'
6
+ require 'yaml'
5
7
 
6
8
  begin
7
9
  require 'kuby/plugins/rails_app/generators/kuby'
@@ -13,6 +15,8 @@ module Kuby
13
15
  autoload :CLIBase, 'kuby/cli_base'
14
16
  autoload :Commands, 'kuby/commands'
15
17
  autoload :Definition, 'kuby/definition'
18
+ autoload :Dependable, 'kuby/dependable'
19
+ autoload :Dependency, 'kuby/dependency'
16
20
  autoload :Docker, 'kuby/docker'
17
21
  autoload :Environment, 'kuby/environment'
18
22
  autoload :Kubernetes, 'kuby/kubernetes'
@@ -22,6 +26,7 @@ module Kuby
22
26
  autoload :Plugins, 'kuby/plugins'
23
27
  autoload :Tasks, 'kuby/tasks'
24
28
  autoload :TrailingHash, 'kuby/trailing_hash'
29
+ autoload :Utils, 'kuby/utils'
25
30
 
26
31
  DEFAULT_ENV = 'development'.freeze
27
32
  DEFAULT_DB_USER = 'root'.freeze
@@ -119,6 +124,14 @@ module Kuby
119
124
  @packages ||= {}
120
125
  end
121
126
 
127
+ def register_dependable(name, version_or_callable)
128
+ dependables[name] = Dependable.new(name, version_or_callable)
129
+ end
130
+
131
+ def dependables
132
+ @dependables ||= {}
133
+ end
134
+
122
135
  def env=(env_name)
123
136
  @env = env_name.to_s
124
137
  end
@@ -128,6 +141,18 @@ module Kuby
128
141
  (@env || Rails.env rescue nil || DEFAULT_ENV).to_s
129
142
  end
130
143
  end
144
+
145
+ def load_rake_tasks!
146
+ Rake::TaskManager.record_task_metadata = true
147
+
148
+ Kuby.plugins.each do |_, plugin_klass|
149
+ plugin_klass.task_dirs.each do |task_dir|
150
+ Dir.glob(File.join(task_dir, '*.rake')).each do |path|
151
+ Rake.load_rakefile(path)
152
+ end
153
+ end
154
+ end
155
+ end
131
156
  end
132
157
  end
133
158
 
@@ -136,6 +161,7 @@ Kuby.register_provider(:docker_desktop, Kuby::Kubernetes::DockerDesktopProvider)
136
161
  Kuby.register_provider(:bare_metal, Kuby::Kubernetes::BareMetalProvider)
137
162
 
138
163
  # plugins
164
+ Kuby.register_plugin(:system, Kuby::Plugins::System)
139
165
  Kuby.register_plugin(:rails_app, Kuby::Plugins::RailsApp::Plugin)
140
166
  Kuby.register_plugin(:nginx_ingress, Kuby::Plugins::NginxIngress)
141
167
 
@@ -156,3 +182,12 @@ Kuby.register_package(:c_toolchain,
156
182
  )
157
183
 
158
184
  Kuby.register_package(:git, 'git')
185
+
186
+ # dependables
187
+ Kuby.register_dependable(:kubectl, KubectlRb::KUBECTL_VERSION)
188
+ Kuby.register_dependable(:helm, HelmRb::HELM_VERSION)
189
+ Kuby.register_dependable(:kubernetes, -> {
190
+ version_info = Kuby.environment.kubernetes.provider.kubernetes_cli.version
191
+ version = version_info.dig('serverVersion', 'gitVersion')
192
+ version.sub(/\Av/, '')
193
+ })