kuby-core 0.7.2 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -0
  3. data/Gemfile +1 -0
  4. data/README.md +11 -1
  5. data/bin/kuby +4 -0
  6. data/kuby-core.gemspec +9 -4
  7. data/lib/kuby.rb +58 -19
  8. data/lib/kuby/basic_logger.rb +13 -0
  9. data/lib/kuby/cli_base.rb +81 -8
  10. data/lib/kuby/commands.rb +244 -0
  11. data/lib/kuby/definition.rb +1 -11
  12. data/lib/kuby/dev_setup.rb +255 -0
  13. data/lib/kuby/docker.rb +1 -0
  14. data/lib/kuby/docker/bundler_phase.rb +3 -3
  15. data/lib/kuby/docker/cli.rb +13 -1
  16. data/lib/kuby/docker/dev_spec.rb +131 -0
  17. data/lib/kuby/docker/dockerfile.rb +16 -1
  18. data/lib/kuby/docker/layer.rb +4 -4
  19. data/lib/kuby/docker/layer_stack.rb +4 -0
  20. data/lib/kuby/docker/local_tags.rb +4 -0
  21. data/lib/kuby/docker/metadata.rb +18 -38
  22. data/lib/kuby/docker/package_phase.rb +2 -2
  23. data/lib/kuby/docker/setup_phase.rb +3 -2
  24. data/lib/kuby/docker/spec.rb +42 -16
  25. data/lib/kuby/docker/timestamp_tag.rb +6 -0
  26. data/lib/kuby/environment.rb +15 -2
  27. data/lib/kuby/kubernetes.rb +9 -11
  28. data/lib/kuby/kubernetes/deploy_task.rb +4 -1
  29. data/lib/kuby/kubernetes/deployer.rb +70 -15
  30. data/lib/kuby/kubernetes/{minikube_provider.rb → docker_desktop_provider.rb} +8 -4
  31. data/lib/kuby/kubernetes/provider.rb +12 -8
  32. data/lib/kuby/kubernetes/spec.rb +30 -29
  33. data/lib/kuby/plugin.rb +59 -0
  34. data/lib/kuby/plugin_registry.rb +27 -0
  35. data/lib/kuby/plugins.rb +6 -0
  36. data/lib/kuby/plugins/nginx_ingress.rb +71 -0
  37. data/lib/kuby/plugins/rails_app.rb +18 -0
  38. data/lib/kuby/plugins/rails_app/asset_copy_task.rb +117 -0
  39. data/lib/kuby/plugins/rails_app/assets.rb +347 -0
  40. data/lib/kuby/plugins/rails_app/database.rb +74 -0
  41. data/lib/kuby/{kubernetes/plugins → plugins}/rails_app/generators/kuby.rb +14 -16
  42. data/lib/kuby/plugins/rails_app/mysql.rb +152 -0
  43. data/lib/kuby/plugins/rails_app/plugin.rb +593 -0
  44. data/lib/kuby/plugins/rails_app/postgres.rb +143 -0
  45. data/lib/kuby/plugins/rails_app/rewrite_db_config.rb +11 -0
  46. data/lib/kuby/plugins/rails_app/sqlite.rb +32 -0
  47. data/lib/kuby/plugins/rails_app/tasks.rake +36 -0
  48. data/lib/kuby/rails_commands.rb +89 -0
  49. data/lib/kuby/railtie.rb +0 -4
  50. data/lib/kuby/tasks.rb +85 -31
  51. data/lib/kuby/version.rb +1 -1
  52. data/spec/docker/metadata_spec.rb +84 -0
  53. data/spec/docker/spec_spec.rb +266 -0
  54. data/spec/docker/timestamp_tag_spec.rb +54 -4
  55. data/spec/dummy/Gemfile +54 -0
  56. data/spec/dummy/Gemfile.lock +223 -0
  57. data/spec/dummy/README.md +24 -0
  58. data/spec/dummy/Rakefile +6 -0
  59. data/spec/dummy/app/assets/config/manifest.js +2 -0
  60. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  61. data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
  62. data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
  63. data/spec/dummy/app/controllers/application_controller.rb +2 -0
  64. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  65. data/spec/dummy/app/javascript/channels/consumer.js +6 -0
  66. data/spec/dummy/app/javascript/channels/index.js +5 -0
  67. data/spec/dummy/app/javascript/packs/application.js +17 -0
  68. data/spec/dummy/app/jobs/application_job.rb +7 -0
  69. data/spec/dummy/app/mailers/application_mailer.rb +4 -0
  70. data/spec/dummy/app/models/application_record.rb +3 -0
  71. data/spec/dummy/app/views/layouts/application.html.erb +15 -0
  72. data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
  73. data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
  74. data/spec/dummy/bin/bundle +114 -0
  75. data/spec/dummy/bin/rails +9 -0
  76. data/spec/dummy/bin/rake +9 -0
  77. data/spec/dummy/bin/setup +36 -0
  78. data/spec/dummy/bin/spring +17 -0
  79. data/spec/dummy/bin/yarn +11 -0
  80. data/spec/dummy/config.ru +5 -0
  81. data/spec/dummy/config/application.rb +19 -0
  82. data/spec/dummy/config/boot.rb +4 -0
  83. data/spec/dummy/config/cable.yml +10 -0
  84. data/spec/dummy/config/credentials.yml.enc +1 -0
  85. data/spec/dummy/config/database.yml +25 -0
  86. data/spec/dummy/config/environment.rb +5 -0
  87. data/spec/dummy/config/environments/development.rb +62 -0
  88. data/spec/dummy/config/environments/production.rb +112 -0
  89. data/spec/dummy/config/environments/test.rb +49 -0
  90. data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
  91. data/spec/dummy/config/initializers/assets.rb +14 -0
  92. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  93. data/spec/dummy/config/initializers/content_security_policy.rb +30 -0
  94. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  95. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  96. data/spec/dummy/config/initializers/inflections.rb +16 -0
  97. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  98. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  99. data/spec/dummy/config/locales/en.yml +33 -0
  100. data/spec/dummy/config/master.key +1 -0
  101. data/spec/dummy/config/puma.rb +38 -0
  102. data/spec/dummy/config/routes.rb +3 -0
  103. data/spec/dummy/config/spring.rb +6 -0
  104. data/spec/dummy/config/storage.yml +34 -0
  105. data/spec/dummy/db/seeds.rb +7 -0
  106. data/spec/dummy/package.json +11 -0
  107. data/spec/dummy/public/404.html +67 -0
  108. data/spec/dummy/public/422.html +67 -0
  109. data/spec/dummy/public/500.html +66 -0
  110. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  111. data/spec/dummy/public/apple-touch-icon.png +0 -0
  112. data/spec/dummy/public/favicon.ico +0 -0
  113. data/spec/dummy/public/robots.txt +1 -0
  114. data/spec/dummy/test/application_system_test_case.rb +5 -0
  115. data/spec/dummy/test/channels/application_cable/connection_test.rb +11 -0
  116. data/spec/dummy/test/test_helper.rb +13 -0
  117. data/spec/dummy/tmp/cache/bootsnap-load-path-cache +0 -0
  118. data/spec/spec_helper.rb +77 -2
  119. data/spec/support/docker/fake_cli.rb +54 -0
  120. data/spec/support/docker/remote/fake_client.rb +16 -0
  121. data/spec/trailing_hash_spec.rb +23 -0
  122. metadata +139 -30
  123. data/lib/ext/krane/kubernetes_resource.rb +0 -16
  124. data/lib/kuby/kubernetes/plugin.rb +0 -55
  125. data/lib/kuby/kubernetes/plugins.rb +0 -8
  126. data/lib/kuby/kubernetes/plugins/nginx_ingress.rb +0 -73
  127. data/lib/kuby/kubernetes/plugins/rails_app.rb +0 -16
  128. data/lib/kuby/kubernetes/plugins/rails_app/database.rb +0 -79
  129. data/lib/kuby/kubernetes/plugins/rails_app/mysql.rb +0 -154
  130. data/lib/kuby/kubernetes/plugins/rails_app/plugin.rb +0 -379
  131. data/lib/kuby/kubernetes/plugins/rails_app/postgres.rb +0 -142
  132. data/lib/kuby/kubernetes/plugins/rails_app/rewrite_db_config.rb +0 -13
  133. data/lib/kuby/kubernetes/plugins/rails_app/sqlite.rb +0 -30
  134. data/lib/kuby/kubernetes/plugins/rails_app/tasks.rake +0 -28
  135. data/lib/kuby/tasks/kuby.rake +0 -70
@@ -0,0 +1,143 @@
1
+ require 'kube-dsl'
2
+ require 'kuby/kube-db'
3
+
4
+ module Kuby
5
+ module Plugins
6
+ module RailsApp
7
+ class Postgres < ::Kuby::Plugin
8
+ ROLE = 'web'.freeze
9
+
10
+ attr_reader :environment, :configs
11
+
12
+ def initialize(environment, configs)
13
+ @environment = environment
14
+ @configs = configs
15
+
16
+ user(config['username'])
17
+ password(config['password'])
18
+ end
19
+
20
+ def name
21
+ :postgres
22
+ end
23
+
24
+ def resources
25
+ @resources ||= [secret, database]
26
+ end
27
+
28
+ def after_configuration
29
+ environment.docker.package_phase.add(:postgres_dev)
30
+ environment.docker.package_phase.add(:postgres_client)
31
+ end
32
+
33
+ def host
34
+ # host is the same as the name thanks to k8s DNS
35
+ @host ||= database.metadata.name
36
+ end
37
+
38
+ def rewritten_configs
39
+ # deep dup
40
+ @rewritten_configs ||= Marshal.load(Marshal.dump(configs)).tap do |new_configs|
41
+ new_configs[environment.name]['host'] = host
42
+ end
43
+ end
44
+
45
+ def user(user)
46
+ secret do
47
+ data do
48
+ set :POSTGRES_USER, user
49
+ end
50
+ end
51
+ end
52
+
53
+ def password(password)
54
+ secret do
55
+ data do
56
+ set :POSTGRES_PASSWORD, password
57
+ end
58
+ end
59
+ end
60
+
61
+ def secret(&block)
62
+ context = self
63
+
64
+ @secret ||= KubeDSL.secret do
65
+ metadata do
66
+ name "#{context.base_name}-postgres-secret"
67
+ namespace context.kubernetes.namespace.metadata.name
68
+ end
69
+
70
+ type 'Opaque'
71
+ end
72
+
73
+ @secret.instance_eval(&block) if block
74
+ @secret
75
+ end
76
+
77
+ def database(&block)
78
+ context = self
79
+
80
+ @database ||= Kuby::KubeDB.postgres do
81
+ api_version 'kubedb.com/v1alpha1'
82
+
83
+ metadata do
84
+ name "#{context.base_name}-postgres"
85
+ namespace context.kubernetes.namespace.metadata.name
86
+ end
87
+
88
+ spec do
89
+ database_secret do
90
+ secret_name context.secret.metadata.name
91
+ end
92
+
93
+ version '11.2'
94
+ standby_mode 'Hot'
95
+ streaming_mode 'asynchronous'
96
+ storage_type 'Durable'
97
+
98
+ storage do
99
+ storage_class_name context.kubernetes.provider.storage_class_name
100
+ access_modes ['ReadWriteOnce']
101
+
102
+ resources do
103
+ requests do
104
+ add :storage, '10Gi'
105
+ end
106
+ end
107
+ end
108
+
109
+ termination_policy 'DoNotTerminate'
110
+ end
111
+ end
112
+
113
+ @database.instance_eval(&block) if block
114
+ @database
115
+ end
116
+
117
+ def base_name
118
+ @base_name ||= "#{kubernetes.selector_app}-#{ROLE}"
119
+ end
120
+
121
+ def kubernetes
122
+ environment.kubernetes
123
+ end
124
+
125
+ private
126
+
127
+ def config
128
+ configs[environment.name]
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ Kuby.register_package(:postgres_dev,
136
+ debian: 'postgresql-client',
137
+ alpine: 'postgresql-dev'
138
+ )
139
+
140
+ Kuby.register_package(:postgres_client,
141
+ debian: 'postgresql-client',
142
+ alpine: 'postgresql-client'
143
+ )
@@ -0,0 +1,11 @@
1
+ module Kuby
2
+ module Plugins
3
+ module RailsApp
4
+ class RewriteDbConfig
5
+ def apply_to(dockerfile)
6
+ dockerfile.run('bundle exec rake kuby:rails_app:db:rewrite_config')
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,32 @@
1
+ module Kuby
2
+ module Plugins
3
+ module RailsApp
4
+ class Sqlite < ::Kuby::Plugin
5
+ attr_reader :environment
6
+
7
+ def initialize(environment, *)
8
+ @environment = environment
9
+ end
10
+
11
+ def after_configuration
12
+ environment.docker.package_phase.add(:sqlite_dev)
13
+ environment.docker.package_phase.add(:sqlite_client)
14
+ end
15
+
16
+ def name
17
+ :sqlite
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ Kuby.register_package(:sqlite_dev,
25
+ debian: 'libsqlite3-dev',
26
+ alpine: 'sqlite-dev'
27
+ )
28
+
29
+ Kuby.register_package(:sqlite_client,
30
+ debian: 'sqlite3',
31
+ alpine: 'sqlite'
32
+ )
@@ -0,0 +1,36 @@
1
+ require 'rake'
2
+
3
+ namespace :kuby do
4
+ namespace :rails_app do
5
+ namespace :db do
6
+ task :rewrite_config do
7
+ Kuby.load!
8
+
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
+
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}")
15
+ end
16
+ end
17
+
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
24
+ end
25
+ end
26
+ end
27
+
28
+ namespace :assets do
29
+ task :copy do
30
+ Kuby.load!
31
+ assets = Kuby.environment.kubernetes.plugin(:rails_assets)
32
+ assets.copy_task.run
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,89 @@
1
+ module Kuby
2
+ class Args
3
+ attr_reader :args, :flag_aliases
4
+
5
+ def initialize(args, flag_aliases = [])
6
+ @args = args
7
+ @flag_aliases = flag_aliases
8
+ end
9
+
10
+ def [](flag)
11
+ idx = find_arg_index(flag)
12
+ idx ? args[idx] : nil
13
+ end
14
+
15
+ def []=(flag, new_value)
16
+ idx = find_arg_index(flag)
17
+
18
+ if idx
19
+ args[idx] = new_value
20
+ else
21
+ @args += [flag, new_value]
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def find_arg_index(flag)
28
+ idx = args.find_index do |arg|
29
+ flag_aliases.any? { |fas| fas.include?(arg) && fas.include?(flag) }
30
+ end
31
+
32
+ idx ? idx + 1 : nil
33
+ end
34
+ end
35
+
36
+ class RailsCommands
37
+ PREFIX = %w(bundle exec).freeze
38
+ SERVER_ARG_ALIASES = [['--binding', '-b'], ['-p', '--port']].freeze
39
+
40
+ class << self
41
+ def run(args = ARGV)
42
+ command = args[0]
43
+
44
+ if command == 'rails'
45
+ subcommand = args[1]
46
+ arglist = nil
47
+
48
+ case subcommand
49
+ when 'server', 's'
50
+ arglist = Args.new([*PREFIX, *args], SERVER_ARG_ALIASES)
51
+ arglist['-b'] ||= '0.0.0.0'
52
+ arglist['-p'] ||= '3000'
53
+ when 'runner', 'r'
54
+ when 'console', 'c'
55
+ else
56
+ return
57
+ end
58
+ elsif command == 'rake'
59
+ arglist = Args.new([*PREFIX, *args])
60
+ end
61
+
62
+ setup
63
+
64
+ arglist ||= Args.new([*PREFIX, *args])
65
+ tasks = Kuby::Tasks.new(environment)
66
+ tasks.remote_exec(arglist.args)
67
+ end
68
+
69
+ private
70
+
71
+ def setup
72
+ require 'kuby'
73
+ Kuby.load!
74
+ end
75
+
76
+ def kubernetes_cli
77
+ kubernetes.provider.kubernetes.cli
78
+ end
79
+
80
+ def kubernetes
81
+ environment.kubernetes
82
+ end
83
+
84
+ def environment
85
+ Kuby.definition.environment
86
+ end
87
+ end
88
+ end
89
+ end
@@ -3,10 +3,6 @@ require 'rails/railtie'
3
3
 
4
4
  module Kuby
5
5
  class Railtie < ::Rails::Railtie
6
- rake_tasks do
7
- load File.expand_path(File.join('tasks', 'kuby.rake'), __dir__)
8
- end
9
-
10
6
  initializer 'kuby.health_check_middleware' do |app|
11
7
  app.middleware.use Kuby::Middleware::HealthCheck
12
8
  end
@@ -2,43 +2,44 @@ require 'rouge'
2
2
 
3
3
  module Kuby
4
4
  class Tasks
5
- attr_reader :definition
5
+ attr_reader :environment
6
6
 
7
- def initialize(definition)
8
- @definition = definition
7
+ def initialize(environment)
8
+ @environment = environment
9
9
  end
10
10
 
11
11
  def print_dockerfile
12
12
  theme = Rouge::Themes::Base16::Solarized.new
13
13
  formatter = Rouge::Formatters::Terminal256.new(theme)
14
14
  lexer = Rouge::Lexers::Docker.new
15
- tokens = lexer.lex(Kuby.definition.docker.to_dockerfile.to_s)
15
+ tokens = lexer.lex(Kuby.environment.docker.to_dockerfile.to_s)
16
16
  puts formatter.format(tokens)
17
17
  end
18
18
 
19
19
  def setup
20
- definition.kubernetes.setup
20
+ environment.kubernetes.setup
21
21
  end
22
22
 
23
23
  def build
24
+ build_args = {}
25
+
26
+ unless ENV.fetch('RAILS_MASTER_KEY', '').empty?
27
+ build_args['RAILS_MASTER_KEY'] = ENV['RAILS_MASTER_KEY']
28
+ end
29
+
24
30
  docker.cli.build(
25
31
  dockerfile: docker.to_dockerfile,
26
32
  image_url: docker.metadata.image_url,
27
- tags: docker.metadata.tags
28
- )
29
- end
30
-
31
- def run
32
- dockerfile = docker.to_dockerfile
33
-
34
- docker.cli.run(
35
- image_url: docker.metadata.image_url,
36
- tag: 'latest',
37
- ports: dockerfile.exposed_ports
33
+ tags: docker.metadata.tags,
34
+ build_args: build_args
38
35
  )
39
36
  end
40
37
 
41
38
  def push
39
+ if environment.development?
40
+ fail 'Cannot push Docker images built for the development environment'
41
+ end
42
+
42
43
  hostname = docker.metadata.image_hostname
43
44
 
44
45
  unless docker.cli.auths.include?(hostname)
@@ -72,12 +73,12 @@ module Kuby
72
73
  end
73
74
  end
74
75
 
75
- def deploy
76
- definition.kubernetes.deploy
76
+ def deploy(tag = nil)
77
+ environment.kubernetes.deploy(tag)
77
78
  end
78
79
 
79
80
  def rollback
80
- definition.kubernetes.rollback
81
+ environment.kubernetes.rollback
81
82
  end
82
83
 
83
84
  def print_resources
@@ -106,26 +107,65 @@ module Kuby
106
107
  kubernetes_cli.run_cmd(['-n', namespace, 'get', 'pods'])
107
108
  end
108
109
 
109
- def remote_shell
110
+ def remote_exec(cmd)
110
111
  first_pod = get_first_pod
111
- shell = docker.distro_spec.shell_exe
112
- kubernetes_cli.exec_cmd(shell, namespace, first_pod.dig('metadata', 'name'))
112
+ kubernetes_cli.exec_cmd(cmd, namespace, first_pod.dig('metadata', 'name'))
113
113
  end
114
114
 
115
- def remote_console
115
+ def remote_system(cmd)
116
116
  first_pod = get_first_pod
117
+ kubernetes_cli.system_cmd(cmd, namespace, first_pod.dig('metadata', 'name'))
118
+ end
117
119
 
118
- kubernetes_cli.exec_cmd(
119
- 'bundle exec rails console', namespace, first_pod.dig('metadata', 'name')
120
- )
120
+ def remote_shell
121
+ remote_exec(docker.distro_spec.shell_exe)
122
+ end
123
+
124
+ def remote_console
125
+ remote_exec('bundle exec rails console')
121
126
  end
122
127
 
123
128
  def remote_dbconsole
124
- first_pod = get_first_pod
129
+ remote_exec('bundle exec rails dbconsole')
130
+ end
131
+
132
+ def remote_restart
133
+ deployment = rails_app.deployment.metadata.name
134
+ kubernetes_cli.restart_deployment(namespace, deployment)
135
+ end
136
+
137
+ def dev_deployment_ok
138
+ return true unless Kuby.environment.development?
125
139
 
126
- kubernetes_cli.exec_cmd(
127
- 'bundle exec rails dbconsole', namespace, first_pod.dig('metadata', 'name')
140
+ deployments = kubernetes_cli.get_objects(
141
+ 'deployments', namespace, match_labels.serialize
128
142
  )
143
+
144
+ if deployments.empty?
145
+ puts 'No development environment detected.'
146
+ STDOUT.write('Set up development environment? (y/n): ')
147
+ answer = STDIN.gets.strip.downcase
148
+ return false unless answer =~ /ye?s?/
149
+ return DevSetup.new(environment).run
150
+ else
151
+ depl = deployments.first
152
+ deployed_checksum = depl.dig('metadata', 'annotations', 'getkuby.io/dockerfile-checksum')
153
+ current_checksum = docker.to_dockerfile.checksum
154
+
155
+ if deployed_checksum != current_checksum
156
+ puts "Development environment appears to be out-of-date."
157
+ puts "Environment checksum: #{deployed_checksum}"
158
+ puts "Current checksum: #{current_checksum}"
159
+ STDOUT.write('Update development environment? (y/n): ')
160
+ answer = STDIN.gets.strip.downcase
161
+ # return true here to prevent letting an out-of-date deployment
162
+ # stop us from running commands
163
+ return true unless answer =~ /ye?s?/
164
+ return DevSetup.new(environment).run
165
+ end
166
+ end
167
+
168
+ true
129
169
  end
130
170
 
131
171
  private
@@ -135,6 +175,12 @@ module Kuby
135
175
  'pods', namespace, match_labels.serialize
136
176
  )
137
177
 
178
+ # consider only "Running" pods that aren't marked for deletion
179
+ pods.select! do |pod|
180
+ pod.dig('status', 'phase') == 'Running' &&
181
+ !pod.dig('metadata', 'deletionTimestamp')
182
+ end
183
+
138
184
  if pods.empty?
139
185
  raise Kuby::Kubernetes::MissingResourceError,
140
186
  "Couldn't find any running pods in namespace '#{namespace}' :("
@@ -161,12 +207,20 @@ module Kuby
161
207
  kubernetes.provider.kubernetes_cli
162
208
  end
163
209
 
210
+ def helm_cli
211
+ kubernetes.provider.helm_cli
212
+ end
213
+
214
+ def docker_cli
215
+ docker.cli
216
+ end
217
+
164
218
  def kubernetes
165
- Kuby.definition.kubernetes
219
+ Kuby.environment.kubernetes
166
220
  end
167
221
 
168
222
  def docker
169
- Kuby.definition.docker
223
+ Kuby.environment.docker
170
224
  end
171
225
  end
172
226
  end