kuber_kit 0.5.6 → 0.6.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 185201d6f305a1e69b2d5ec982288234454404bb9b87501130f159fb58a3b97a
4
- data.tar.gz: e411255031c65afe38e7b0faa20e9b578b2d3eca93a3bb9dc013766a59c7d2b1
3
+ metadata.gz: 32c19efd73a0f79e6dd009a9e6700c184b78eacde4be6c7eb3e9571a6aa5977d
4
+ data.tar.gz: 6c66868a7a280ecaccc6dcb44ee75a929ecbb057545f412dab2f57e4e8c45bc9
5
5
  SHA512:
6
- metadata.gz: 936fd6032488908db1fffe95f736dd05042c499f2995be2bc28566b2f65d9d5b35150acc0cf08de50442c16408d56d623292bb8e051215bfc15b8aba804266cc
7
- data.tar.gz: c81b1a227cf5690d675b0b8d269382f0bb6d13ed71cfc3442679e1bd7471b995e02e7177b6c93bfb6955792bd591708c0ea017f9ea52291992bbbd0e5b33c0e2
6
+ metadata.gz: 8b1316dd6e65c9f81db7450c4e86c398357cd429054965ddff80634744f1ab5b1acedb638cd51c9c65040edd0c09c67429d5f884eef6c443ddb0e6bf558bd878
7
+ data.tar.gz: dac99cdc86d70f8f9424f6cb9aee0e7f5630e5407f878266c6373740015a5664c3ea6c27a29c9f39985b738bc7665281f9f9ced846436f251598da16bc6517f8
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ **0.6.0**
2
+ - Cleanup old image build dirs
3
+ - Add rotation to deployment log file
4
+
5
+ **0.5.10**
6
+ - Fix a regression when deployment result would not be properly returned as json.
7
+
8
+ **0.5.9**
9
+ - Added an ability to set custom user
10
+ - Allow setting environment variable in docker strategy
11
+ - Properly stop deployment if image compilation is failed
12
+
13
+ **0.5.8**
14
+ - Update gemspec to support ruby 2.5
15
+
16
+ **0.5.7**
17
+ - Look for kuber_kit root path in parent folders, so kit command will work in sub-folders
18
+
1
19
  **0.5.6**
2
20
  - Pre-process env file if it has .erb extension
3
21
  - Allow attaching env file from configuration to docker container
data/Gemfile.lock CHANGED
@@ -1,10 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kuber_kit (0.5.6)
4
+ kuber_kit (0.6.0)
5
5
  cli-ui
6
6
  contracts-lite
7
- dry-auto_inject
7
+ dry-auto_inject (~> 0.7.0)
8
+ dry-container (~> 0.7.2)
8
9
  net-ssh
9
10
  thor
10
11
  tty-prompt
data/TODO.md CHANGED
@@ -1,8 +1,5 @@
1
- - add kit get method for more interactive kubernetes
2
1
  - env files should use a separate deployment method (with change detection)
3
2
  - add automatical confirmation support for service deployer
4
3
  - template should be able to set default attributes
5
4
  - template should be able to depend on image?
6
- - cleanup image builds older than some date
7
- - add some rotation for deploy log
8
5
  - kit status should show the list of services and their status, with ability to select & view logs
@@ -3,7 +3,8 @@ apiVersion: apps/v1
3
3
  kind: Deployment
4
4
  metadata:
5
5
  labels:
6
- app: <%= service_uri %>
6
+ app: <%= service_uri %>
7
+ user: <%= KuberKit.user %>
7
8
  name: <%= service_uri %>
8
9
  spec:
9
10
  replicas: 1
@@ -0,0 +1,5 @@
1
+ FROM <%= image_url(:ruby) %>
2
+
3
+ RUN not_existing_command
4
+
5
+ CMD ["tail", "-f", "/dev/null"]
@@ -0,0 +1,4 @@
1
+ KuberKit
2
+ .define_image(:failing_app)
3
+ .registry(:default)
4
+ .depends_on(:ruby, :app_sources)
@@ -0,0 +1,6 @@
1
+ KuberKit
2
+ .define_service(:failing_app)
3
+ .depends_on(:env_file)
4
+ .template(:service)
5
+ .images(:failing_app)
6
+ .tags("app", "minimal")
data/kuber_kit.gemspec CHANGED
@@ -24,11 +24,12 @@ Gem::Specification.new do |spec|
24
24
  spec.require_paths = ["lib"]
25
25
 
26
26
  spec.add_dependency "contracts-lite"
27
- spec.add_dependency "dry-auto_inject"
27
+ spec.add_dependency "dry-auto_inject", "~> 0.7.0"
28
28
  spec.add_dependency "thor"
29
29
  spec.add_dependency "cli-ui"
30
30
  spec.add_dependency "net-ssh"
31
31
  spec.add_dependency "tty-prompt"
32
+ spec.add_dependency "dry-container", "~> 0.7.2"
32
33
 
33
34
  spec.add_development_dependency "bundler", "~> 1.17"
34
35
  spec.add_development_dependency "rake", "~> 10.0"
data/lib/kuber_kit.rb CHANGED
@@ -79,9 +79,11 @@ module KuberKit
79
79
  end
80
80
 
81
81
  module Tools
82
+ autoload :BuildDirCleaner, 'tools/build_dir_cleaner'
82
83
  autoload :FilePresenceChecker, 'tools/file_presence_checker'
83
84
  autoload :LoggerFactory, 'tools/logger_factory'
84
85
  autoload :ProcessCleaner, 'tools/process_cleaner'
86
+ autoload :WorkdirDetector, 'tools/workdir_detector'
85
87
  end
86
88
 
87
89
  module Shell
@@ -152,6 +154,7 @@ module KuberKit
152
154
  autoload :ActionHandler, 'service_deployer/action_handler'
153
155
  autoload :StrategyDetector, 'service_deployer/strategy_detector'
154
156
  autoload :Deployer, 'service_deployer/deployer'
157
+ autoload :DeploymentOptionsSelector, 'service_deployer/deployment_options_selector'
155
158
  autoload :ServiceListResolver, 'service_deployer/service_list_resolver'
156
159
  autoload :ServiceDependencyResolver, 'service_deployer/service_dependency_resolver'
157
160
 
@@ -169,6 +172,7 @@ module KuberKit
169
172
  end
170
173
 
171
174
  module Actions
175
+ autoload :ActionResult, 'actions/action_result'
172
176
  autoload :ImageCompiler, 'actions/image_compiler'
173
177
  autoload :EnvFileReader, 'actions/env_file_reader'
174
178
  autoload :TemplateReader, 'actions/template_reader'
@@ -274,6 +278,11 @@ module KuberKit
274
278
  KuberKit::Core::ContextHelper::BaseHelper.class_exec(&proc)
275
279
  end
276
280
 
281
+ def set_user(value)
282
+ @user = value
283
+ @user_id = nil
284
+ end
285
+
277
286
  def user
278
287
  @user ||= ENV["KUBER_KIT_USERNAME"] || `whoami`.chomp
279
288
  end
@@ -0,0 +1,32 @@
1
+ class KuberKit::Actions::ActionResult
2
+ attr_reader :finished_tasks, :all_results, :error
3
+
4
+ def initialize()
5
+ @all_results = {}
6
+ @started_tasks = []
7
+ @finished_tasks = []
8
+ @mutex = Mutex.new
9
+ end
10
+
11
+ def start_task(task)
12
+ @mutex.synchronize do
13
+ @started_tasks.push(task)
14
+ end
15
+ end
16
+
17
+ def finish_task(task, result = nil)
18
+ @mutex.synchronize do
19
+ @started_tasks.delete(task)
20
+ @finished_tasks.push(task)
21
+ @all_results[task] = result
22
+ end
23
+ end
24
+
25
+ def failed!(error)
26
+ @error = error
27
+ end
28
+
29
+ def succeeded?
30
+ @error.nil? && @started_tasks.empty?
31
+ end
32
+ end
@@ -4,6 +4,7 @@ class KuberKit::Actions::ConfigurationLoader
4
4
  "core.image_store",
5
5
  "core.service_store",
6
6
  "core.configuration_store",
7
+ "tools.workdir_detector",
7
8
  "artifacts_sync.artifacts_updater",
8
9
  "shell.local_shell",
9
10
  "ui",
@@ -12,7 +13,7 @@ class KuberKit::Actions::ConfigurationLoader
12
13
 
13
14
  Contract Hash => Any
14
15
  def call(options)
15
- root_path = options[:path] || File.join(Dir.pwd, configs.kuber_kit_dirname)
16
+ root_path = workdir_detector.call(options)
16
17
  images_path = options[:images_path] || File.join(root_path, configs.images_dirname)
17
18
  services_path = options[:services_path] || File.join(root_path, configs.services_dirname)
18
19
  infra_path = options[:infra_path] || File.join(root_path, configs.infra_dirname)
@@ -10,38 +10,40 @@ class KuberKit::Actions::ImageCompiler
10
10
 
11
11
  Contract ArrayOf[Symbol], Hash => Any
12
12
  def call(image_names, options)
13
+ compilation_result = KuberKit::Actions::ActionResult.new()
14
+
13
15
  build_id = generate_build_id
14
16
  build_server_pool = build_server_pool_factory.create()
15
17
 
16
- compiled_images = []
17
- compilation_result = {}
18
18
  image_dependency_resolver.each_with_deps(image_names) do |dep_image_names|
19
19
  ui.print_debug("ImageCompiler", "Scheduling to compile: #{dep_image_names.inspect}. Limit: #{configs.compile_simultaneous_limit}")
20
- result = compile_simultaneously(dep_image_names, build_id, build_server_pool)
21
- compiled_images += dep_image_names
22
- compilation_result = compilation_result.merge(result)
20
+
21
+ if compilation_result.succeeded?
22
+ compile_simultaneously(dep_image_names, build_id, build_server_pool, compilation_result)
23
+ end
23
24
  end
24
25
 
25
26
  build_server_pool.disconnect_all
26
27
 
27
- { images: compiled_images, compilation: compilation_result }
28
+ compilation_result
28
29
  rescue KuberKit::Error => e
29
30
  ui.print_error("Error", e.message)
30
31
 
32
+ compilation_result.failed!(e.message)
33
+
31
34
  false
32
35
  end
33
36
 
34
37
  private
35
- def compile_simultaneously(image_names, build_id, build_server_pool)
38
+ def compile_simultaneously(image_names, build_id, build_server_pool, compilation_result)
36
39
  task_group = ui.create_task_group
37
- compiler_result = {}
38
40
  image_names.map do |image_name|
39
41
 
40
42
  ui.print_debug("ImageCompiler", "Started compiling: #{image_name.to_s.green}")
41
43
  task_group.add("Compiling #{image_name.to_s.yellow}") do |task|
42
- shell = build_server_pool.get_shell
43
-
44
- compiler_result[image_name] = image_compiler.call(shell, image_name, build_id)
44
+ compilation_result.start_task(image_name)
45
+ image_result = compile_one(image_name, build_id, build_server_pool)
46
+ compilation_result.finish_task(image_name, image_result)
45
47
 
46
48
  task.update_title("Compiled #{image_name.to_s.green}")
47
49
  ui.print_debug("ImageCompiler", "Finished compiling: #{image_name}")
@@ -49,7 +51,11 @@ class KuberKit::Actions::ImageCompiler
49
51
 
50
52
  end
51
53
  task_group.wait
52
- compiler_result
54
+ end
55
+
56
+ def compile_one(image_name, build_id, build_server_pool)
57
+ shell = build_server_pool.get_shell
58
+ image_compiler.call(shell, image_name, build_id)
53
59
  end
54
60
 
55
61
  def generate_build_id
@@ -3,6 +3,7 @@ class KuberKit::Actions::ServiceDeployer
3
3
  "actions.image_compiler",
4
4
  "service_deployer.service_list_resolver",
5
5
  "service_deployer.service_dependency_resolver",
6
+ "service_deployer.deployment_options_selector",
6
7
  "core.service_store",
7
8
  "shell.local_shell",
8
9
  "tools.process_cleaner",
@@ -19,13 +20,13 @@ class KuberKit::Actions::ServiceDeployer
19
20
  require_confirmation: Maybe[Bool],
20
21
  ] => Any
21
22
  def call(services:, tags:, skip_services: nil, skip_compile: false, require_confirmation: false)
23
+ deployment_result = KuberKit::Actions::ActionResult.new()
22
24
  current_configuration = KuberKit.current_configuration
23
25
 
24
26
  if services.empty? && tags.empty?
25
- services, tags = show_tags_selection
27
+ services, tags = deployment_options_selector.call()
26
28
  end
27
29
 
28
-
29
30
  disabled_services = current_configuration.disabled_services.map(&:to_s)
30
31
  disabled_services += skip_services if skip_services
31
32
 
@@ -44,54 +45,50 @@ class KuberKit::Actions::ServiceDeployer
44
45
  return false
45
46
  end
46
47
 
47
- services_list = all_service_names.map(&:to_s).map(&:yellow).join(", ")
48
- ui.print_info "ServiceDeployer", "The following services will be deployed: #{services_list}"
49
-
50
- if require_confirmation
51
- result = ui.prompt("Please confirm to continue deployment", ["confirm".green, "cancel".red])
52
- return false unless ["confirm".green, "confirm", "yes"].include?(result)
53
- end
54
-
55
- services = all_service_names.map do |service_name|
56
- service_store.get_service(service_name.to_sym)
48
+ unless allow_deployment?(require_confirmation: require_confirmation, service_names: all_service_names)
49
+ return false
57
50
  end
58
51
 
59
- images_names = services.map(&:images).flatten.uniq
60
-
52
+ # Compile images for all services and dependencies
53
+ images_names = get_image_names(service_names: all_service_names)
61
54
  unless skip_compile
62
- compile_result = compile_images(images_names)
63
- return false unless compile_result
55
+ compilation_result = compile_images(images_names)
56
+
57
+ return false unless compilation_result && compilation_result.succeeded?
64
58
  end
65
59
 
66
- deployed_services = []
67
- deployment_result = {}
68
60
  service_dependency_resolver.each_with_deps(service_names) do |dep_service_names|
69
61
  ui.print_debug("ServiceDeployer", "Scheduling to compile: #{dep_service_names.inspect}. Limit: #{configs.deploy_simultaneous_limit}")
70
- result = deploy_simultaneously(dep_service_names)
71
- deployed_services += dep_service_names
72
- deployment_result = deployment_result.merge(result)
62
+
63
+ if deployment_result.succeeded?
64
+ deploy_simultaneously(dep_service_names, deployment_result)
65
+ end
73
66
  end
74
67
 
75
- { services: all_service_names, deployment: deployment_result }
68
+ deployment_result
76
69
  rescue KuberKit::Error => e
77
70
  ui.print_error("Error", e.message)
78
71
 
72
+ deployment_result.failed!(e.message)
73
+
79
74
  false
80
75
  rescue Interrupt => e
81
76
  process_cleaner.clean
77
+
78
+ false
82
79
  end
83
80
 
84
81
  private
85
- def deploy_simultaneously(service_names)
82
+ def deploy_simultaneously(service_names, deployment_result)
86
83
  task_group = ui.create_task_group
87
84
 
88
- deployer_result = {}
89
-
90
85
  service_names.each do |service_name|
91
86
 
92
87
  ui.print_debug("ServiceDeployer", "Started deploying: #{service_name.to_s.green}")
93
88
  task_group.add("Deploying #{service_name.to_s.yellow}") do |task|
94
- deployer_result[service_name] = service_deployer.call(local_shell, service_name.to_sym)
89
+ deployment_result.start_task(service_name)
90
+ service_result = service_deployer.call(local_shell, service_name.to_sym)
91
+ deployment_result.finish_task(service_name, service_result)
95
92
 
96
93
  task.update_title("Deployed #{service_name.to_s.green}")
97
94
  ui.print_debug("ServiceDeployer", "Finished deploying: #{service_name.to_s.green}")
@@ -99,55 +96,30 @@ class KuberKit::Actions::ServiceDeployer
99
96
  end
100
97
 
101
98
  task_group.wait
102
-
103
- deployer_result
104
99
  end
105
100
 
106
101
  def compile_images(images_names)
107
- return true if images_names.empty?
102
+ return KuberKit::Actions::ActionResult.new if images_names.empty?
108
103
  image_compiler.call(images_names, {})
109
104
  end
110
105
 
111
- def show_tags_selection()
112
- specific_service_option = "deploy specific service"
113
- all_services_option = "deploy all services"
114
-
115
- tags = [specific_service_option, all_services_option]
116
- tags += service_store
117
- .all_definitions
118
- .values
119
- .map(&:to_service_attrs)
120
- .map(&:tags)
121
- .flatten
122
- .uniq
123
- .sort
124
- .map(&:to_s)
125
-
126
- selected_tag = ui.prompt("Please select which tag to deploy", tags)
127
-
128
- if selected_tag == specific_service_option
129
- show_service_selection
130
- elsif selected_tag == all_services_option
131
- [["*"], []]
132
- else
133
- [[], [selected_tag]]
106
+ def get_image_names(service_names:)
107
+ services = service_names.map do |service_name|
108
+ service_store.get_service(service_name.to_sym)
134
109
  end
110
+
111
+ services.map(&:images).flatten.uniq
135
112
  end
136
113
 
137
- def show_service_selection()
138
- services = service_store
139
- .all_definitions
140
- .values
141
- .map(&:service_name)
142
- .uniq
143
- .sort
144
- .map(&:to_s)
145
-
146
- if services.empty?
147
- return [[], []]
114
+ def allow_deployment?(require_confirmation:, service_names:)
115
+ services_list = service_names.map(&:to_s).map(&:yellow).join(", ")
116
+ ui.print_info "ServiceDeployer", "The following services will be deployed: #{services_list}"
117
+
118
+ unless require_confirmation
119
+ return true
148
120
  end
149
121
 
150
- selected_service = ui.prompt("Please select which service to deploy", services)
151
- [[selected_service], []]
122
+ result = ui.prompt("Please confirm to continue deployment", ["confirm".green, "cancel".red])
123
+ return ["confirm".green, "confirm", "yes"].include?(result)
152
124
  end
153
125
  end
data/lib/kuber_kit/cli.rb CHANGED
@@ -10,6 +10,7 @@ class KuberKit::CLI < Thor
10
10
  class_option :ui, :type => :string, :desc => "UI mode (interactive|debug|simple)"
11
11
  class_option :debug, :type => :boolean, aliases: ["-d"]
12
12
  class_option :configuration, :type => :string, aliases: ["-C"]
13
+ class_option :user, :type => :string, aliases: ["-u"]
13
14
 
14
15
  desc "compile IMAGE_NAMES", "Compile image with IMAGE_NAMES (comma-separated)"
15
16
  def compile(image_names_str)
@@ -19,12 +20,15 @@ class KuberKit::CLI < Thor
19
20
  image_names = image_names_str.split(",").map(&:strip).map(&:to_sym)
20
21
 
21
22
  if KuberKit::Container['actions.configuration_loader'].call(options)
22
- result = KuberKit::Container['actions.image_compiler'].call(image_names, options)
23
+ action_result = KuberKit::Container['actions.image_compiler'].call(image_names, options)
23
24
  end
24
25
 
25
- if result
26
+ if action_result && action_result.succeeded?
26
27
  time = (Time.now.to_i - started_at)
27
- print_result("Image compilation finished! (#{time}s)", result: result)
28
+ print_result("Image compilation finished! (#{time}s)", result: {
29
+ images: action_result.finished_tasks,
30
+ compilation: action_result.all_results
31
+ })
28
32
  else
29
33
  exit 1
30
34
  end
@@ -44,7 +48,7 @@ class KuberKit::CLI < Thor
44
48
  KuberKit.current_configuration.deployer_require_confirimation ||
45
49
  false
46
50
  started_at = Time.now.to_i
47
- result = KuberKit::Container['actions.service_deployer'].call(
51
+ action_result = KuberKit::Container['actions.service_deployer'].call(
48
52
  services: (options[:services] || []).flatten.uniq,
49
53
  tags: (options[:tags] || []).flatten.uniq,
50
54
  skip_services: (options[:skip_services] || []).flatten.uniq,
@@ -53,9 +57,12 @@ class KuberKit::CLI < Thor
53
57
  )
54
58
  end
55
59
 
56
- if result
60
+ if action_result && action_result.succeeded?
57
61
  time = (Time.now.to_i - started_at)
58
- print_result("Service deployment finished! (#{time}s)", result: result)
62
+ print_result("Service deployment finished! (#{time}s)", result: {
63
+ services: action_result.finished_tasks,
64
+ deployment: action_result.all_results
65
+ })
59
66
  else
60
67
  exit 1
61
68
  end
@@ -178,8 +185,12 @@ class KuberKit::CLI < Thor
178
185
  KuberKit.set_ui_mode(options[:ui].to_sym)
179
186
  end
180
187
 
188
+ if options[:user]
189
+ KuberKit.set_user(options[:user])
190
+ end
191
+
181
192
  # We should load config before loading any bean, to make sure that bean won't be built with default config
182
- root_path = options[:path] || File.join(Dir.pwd, KuberKit::Container['configs'].kuber_kit_dirname)
193
+ root_path = KuberKit::Container['tools.workdir_detector'].call(options)
183
194
  config_file_path = File.join(root_path, APP_CONFIG_FILENAME)
184
195
  if File.exists?(config_file_path)
185
196
  require config_file_path
@@ -189,21 +200,4 @@ class KuberKit::CLI < Thor
189
200
  def print_result(message, data = {})
190
201
  KuberKit::Container['ui'].print_result(message, data)
191
202
  end
192
-
193
- def cleanup_processes
194
- # Stop all threads
195
- Thread.list.each do |t|
196
- t.abort_on_exception = false
197
- t.report_on_exception = false
198
- Thread.kill(t) if t != Thread.current
199
- end
200
-
201
- # Find all system calls
202
- child_pids_raw = `ps auxww | grep '[K]IT=#{Process.pid}' | awk '{print $2}'`
203
- child_pids = child_pids_raw.to_s.split("\n").reject(&:empty?)
204
- child_pids.each do |pid|
205
- puts "Killing child process: #{pid}"
206
- Process.kill("SIGHUP", pid.to_i)
207
- end
208
- end
209
203
  end
@@ -121,6 +121,10 @@ class KuberKit::Container
121
121
  KuberKit::Core::ContextHelper::ContextHelperFactory.new
122
122
  end
123
123
 
124
+ register "tools.build_dir_cleaner" do
125
+ KuberKit::Tools::BuildDirCleaner.new
126
+ end
127
+
124
128
  register "tools.file_presence_checker" do
125
129
  KuberKit::Tools::FilePresenceChecker.new
126
130
  end
@@ -137,6 +141,10 @@ class KuberKit::Container
137
141
  KuberKit::Tools::ProcessCleaner.new
138
142
  end
139
143
 
144
+ register "tools.workdir_detector" do
145
+ KuberKit::Tools::WorkdirDetector.new
146
+ end
147
+
140
148
  register "shell.bash_commands" do
141
149
  KuberKit::Shell::Commands::BashCommands.new
142
150
  end
@@ -269,6 +277,10 @@ class KuberKit::Container
269
277
  KuberKit::ServiceDeployer::Deployer.new
270
278
  end
271
279
 
280
+ register "service_deployer.deployment_options_selector" do
281
+ KuberKit::ServiceDeployer::DeploymentOptionsSelector.new
282
+ end
283
+
272
284
  register "service_deployer.service_list_resolver" do
273
285
  KuberKit::ServiceDeployer::ServiceListResolver.new
274
286
  end
@@ -2,12 +2,15 @@ class KuberKit::ImageCompiler::ActionHandler
2
2
  include KuberKit::Import[
3
3
  "image_compiler.compiler",
4
4
  "core.image_store",
5
+ "tools.build_dir_cleaner",
5
6
  "configs",
6
7
  ]
7
8
 
8
9
  Contract KuberKit::Shell::AbstractShell, Symbol, String => Any
9
10
  def call(shell, image_name, build_id)
10
11
  image = image_store.get_image(image_name)
12
+
13
+ build_dir_cleaner.call(parent_dir: configs.image_compile_dir)
11
14
 
12
15
  compile_dir = generate_compile_dir(build_id: build_id)
13
16
 
@@ -0,0 +1,49 @@
1
+ class KuberKit::ServiceDeployer::DeploymentOptionsSelector
2
+ include KuberKit::Import[
3
+ "core.service_store",
4
+ "ui"
5
+ ]
6
+
7
+ OPTION_SPECIFIC_SERVICE = "deploy specific service".freeze
8
+ OPTION_ALL_SERVICES = "deploy all services"
9
+
10
+ def call()
11
+ tags = [OPTION_SPECIFIC_SERVICE, OPTION_ALL_SERVICES]
12
+ tags += service_store
13
+ .all_definitions
14
+ .values
15
+ .map(&:to_service_attrs)
16
+ .map(&:tags)
17
+ .flatten
18
+ .uniq
19
+ .sort
20
+ .map(&:to_s)
21
+
22
+ selected_tag = ui.prompt("Please select which tag to deploy", tags)
23
+
24
+ if selected_tag == OPTION_SPECIFIC_SERVICE
25
+ show_service_selection
26
+ elsif selected_tag == OPTION_ALL_SERVICES
27
+ [["*"], []]
28
+ else
29
+ [[], [selected_tag]]
30
+ end
31
+ end
32
+
33
+ def show_service_selection()
34
+ services = service_store
35
+ .all_definitions
36
+ .values
37
+ .map(&:service_name)
38
+ .uniq
39
+ .sort
40
+ .map(&:to_s)
41
+
42
+ if services.empty?
43
+ return [[], []]
44
+ end
45
+
46
+ selected_service = ui.prompt("Please select which service to deploy", services)
47
+ [[selected_service], []]
48
+ end
49
+ end
@@ -20,7 +20,8 @@ class KuberKit::ServiceDeployer::Strategies::Docker < KuberKit::ServiceDeployer:
20
20
  :networks,
21
21
  :expose,
22
22
  :publish,
23
- :env_file_names
23
+ :env_file_names,
24
+ :env_vars
24
25
  ]
25
26
 
26
27
  Contract KuberKit::Shell::AbstractShell, KuberKit::Core::Service => Any
@@ -44,6 +45,7 @@ class KuberKit::ServiceDeployer::Strategies::Docker < KuberKit::ServiceDeployer:
44
45
 
45
46
  env_file_names = strategy_options.fetch(:env_file_names, [])
46
47
  env_files = prepare_env_files(shell, env_file_names)
48
+ env_vars = strategy_options.fetch(:env_vars, {})
47
49
 
48
50
  image_name = strategy_options.fetch(:image_name, nil)
49
51
  if image_name.nil?
@@ -84,6 +86,9 @@ class KuberKit::ServiceDeployer::Strategies::Docker < KuberKit::ServiceDeployer:
84
86
  Array(env_files).each do |env_file|
85
87
  custom_args << "--env-file #{env_file}"
86
88
  end
89
+ env_vars.each do |key, value|
90
+ custom_args << "--env #{key}=#{value}"
91
+ end
87
92
 
88
93
  docker_commands.run(
89
94
  shell, image.remote_registry_url,
@@ -100,6 +100,18 @@ class KuberKit::Shell::LocalShell < KuberKit::Shell::AbstractShell
100
100
  end
101
101
  end
102
102
 
103
+ def list_dirs(path)
104
+ command = %Q{find -L #{path} -type f}
105
+ command += " -name '#{name}'" if name
106
+ exec!(command).split(/[\r\n]+/)
107
+ rescue => e
108
+ if e.message.include?("No such file or directory")
109
+ raise DirNotFoundError.new("Dir not found: #{path}")
110
+ else
111
+ raise e
112
+ end
113
+ end
114
+
103
115
  def wrap_command_with_pid(command)
104
116
  "KIT=#{Process.pid} #{command}"
105
117
  end
@@ -0,0 +1,26 @@
1
+ class KuberKit::Tools::BuildDirCleaner
2
+ include KuberKit::Import[
3
+ "shell.bash_commands",
4
+ "shell.local_shell",
5
+ ]
6
+
7
+ KEEP_DIRS_COUNT = 10
8
+
9
+ def call(parent_dir:)
10
+ dirs_to_delete = get_ancient_builds_dirs(parent_dir: parent_dir)
11
+
12
+ dirs_to_delete.each do |dir|
13
+ bash_commands.rm_rf(local_shell, dir)
14
+ end
15
+ end
16
+
17
+ private
18
+ def get_ancient_builds_dirs(parent_dir:)
19
+ all_dirs = Dir.glob("#{parent_dir}/*")
20
+ skip_dirs = all_dirs
21
+ .sort_by{ |f| File.ctime(f) }
22
+ .reverse[0...KEEP_DIRS_COUNT]
23
+
24
+ all_dirs - skip_dirs
25
+ end
26
+ end
@@ -10,16 +10,17 @@ class KuberKit::Tools::LoggerFactory
10
10
  Logger::FATAL => String::Colors::PURPLE,
11
11
  }
12
12
 
13
+ MAX_LOGS_TO_KEEP = 3
14
+ MAX_LOG_FILE_SIZE = 512000
15
+
13
16
  include KuberKit::Import[
14
17
  "configs",
15
18
  ]
16
19
 
17
- def create(stdout = nil, level = nil)
18
- if !stdout
19
- prepare_log_file(configs.log_file_path)
20
- end
20
+ def create(level: nil)
21
+ prepare_log_file(configs.log_file_path)
21
22
 
22
- logger = Logger.new(stdout || configs.log_file_path)
23
+ logger = Logger.new(configs.log_file_path, MAX_LOGS_TO_KEEP, MAX_LOG_FILE_SIZE)
23
24
 
24
25
  logger.level = level || Logger::DEBUG
25
26
 
@@ -0,0 +1,33 @@
1
+ class KuberKit::Tools::WorkdirDetector
2
+ include KuberKit::Import[
3
+ "configs",
4
+ "tools.file_presence_checker"
5
+ ]
6
+
7
+ def call(options, current_dir: nil)
8
+ current_dir ||= Dir.pwd
9
+ default_dir = File.join(current_dir, configs.kuber_kit_dirname)
10
+ workdir_path = options[:path] || ENV['KUBER_KIT_PATH'] || default_dir
11
+
12
+ unless file_presence_checker.dir_exists?(workdir_path)
13
+ workdir_in_ancestors = find_workdir_in_ancestors(current_dir)
14
+ workdir_path = workdir_in_ancestors if workdir_in_ancestors
15
+ end
16
+
17
+ workdir_path
18
+ end
19
+
20
+ private
21
+ def find_workdir_in_ancestors(dir)
22
+ if dir == "/"
23
+ return nil
24
+ end
25
+
26
+ workdir_path = File.join(dir, configs.kuber_kit_dirname)
27
+ if file_presence_checker.dir_exists?(workdir_path)
28
+ return workdir_path
29
+ end
30
+
31
+ find_workdir_in_ancestors(File.dirname(dir))
32
+ end
33
+ end
@@ -1,3 +1,3 @@
1
1
  module KuberKit
2
- VERSION = "0.5.6"
2
+ VERSION = "0.6.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kuber_kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.6
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Iskander Khaziev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-11 00:00:00.000000000 Z
11
+ date: 2021-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: contracts-lite
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: dry-auto_inject
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: 0.7.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: 0.7.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: thor
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: dry-container
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.7.2
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.7.2
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: bundler
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -184,6 +198,8 @@ files:
184
198
  - example/images/app_sources/Dockerfile
185
199
  - example/images/app_sources/build_context/source.rb
186
200
  - example/images/app_sources/image.rb
201
+ - example/images/failing_app/Dockerfile
202
+ - example/images/failing_app/image.rb
187
203
  - example/images/ruby/Dockerfile
188
204
  - example/images/ruby/image.rb
189
205
  - example/images/ruby_app/Dockerfile
@@ -200,9 +216,11 @@ files:
200
216
  - example/services/compose_app.rb
201
217
  - example/services/docker_app.rb
202
218
  - example/services/env_file.rb
219
+ - example/services/failing_app.rb
203
220
  - example/services/ruby_app.rb
204
221
  - kuber_kit.gemspec
205
222
  - lib/kuber_kit.rb
223
+ - lib/kuber_kit/actions/action_result.rb
206
224
  - lib/kuber_kit/actions/configuration_loader.rb
207
225
  - lib/kuber_kit/actions/env_file_reader.rb
208
226
  - lib/kuber_kit/actions/image_compiler.rb
@@ -288,6 +306,7 @@ files:
288
306
  - lib/kuber_kit/preprocessing/text_preprocessor.rb
289
307
  - lib/kuber_kit/service_deployer/action_handler.rb
290
308
  - lib/kuber_kit/service_deployer/deployer.rb
309
+ - lib/kuber_kit/service_deployer/deployment_options_selector.rb
291
310
  - lib/kuber_kit/service_deployer/service_dependency_resolver.rb
292
311
  - lib/kuber_kit/service_deployer/service_list_resolver.rb
293
312
  - lib/kuber_kit/service_deployer/strategies/abstract.rb
@@ -313,9 +332,11 @@ files:
313
332
  - lib/kuber_kit/template_reader/reader.rb
314
333
  - lib/kuber_kit/template_reader/strategies/abstract.rb
315
334
  - lib/kuber_kit/template_reader/strategies/artifact_file.rb
335
+ - lib/kuber_kit/tools/build_dir_cleaner.rb
316
336
  - lib/kuber_kit/tools/file_presence_checker.rb
317
337
  - lib/kuber_kit/tools/logger_factory.rb
318
338
  - lib/kuber_kit/tools/process_cleaner.rb
339
+ - lib/kuber_kit/tools/workdir_detector.rb
319
340
  - lib/kuber_kit/ui.rb
320
341
  - lib/kuber_kit/ui/api.rb
321
342
  - lib/kuber_kit/ui/debug.rb