kuby-core 0.17.0 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ })