kuber_kit 0.5.8 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 43a9f6570da4774b94202c3bc69218d3ed09f6884f94a0298e08b33c31f0ece4
4
- data.tar.gz: 1f6ab288380f5de3e202de937bd46b6cdc810bfbf4454b2a3109797f7a9ba8e1
3
+ metadata.gz: 03c60b8fd02854d59ccad27ac3e512b726049d55f87f41d9c0ac0256344705ba
4
+ data.tar.gz: e60f2f47da61e2b5c3942878c19c863c2537bd5a6513476bb4a26aea81259674
5
5
  SHA512:
6
- metadata.gz: 4af8a912626d5f37811d2abfa042334654cb950a5e640e6e46d9abb1094d3e54c16341b5e42a1af8d0db68ef433ba5b3147af86fe5cf23b501e93c6fe6f6de4a
7
- data.tar.gz: f357c787ab98eb2173cb7048191eec24fad97489f51a1ec57f38fcbdf695609aee2a96d496bd57f47216188cfcd073d9bcc11391be7ddfb4d77816466a00b0bf
6
+ metadata.gz: 85bfd81c3419a8a44960c89e9e31d06a4775aa143141fdc8da8f46ea207d60a2be53310213a5cc96cf1fe034097c13f09d10256a72d0535bb6ee363d0a12c987
7
+ data.tar.gz: 7182215530a9ee4908e4e483c578764c3bbc63f4d510c89b68bf8a2cb15a5e41bf714eb553b1497ad2236af4e585feb0e6aa810b00bb8e0f3b3ff1357e9717bf
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ **0.6.1**
2
+ - Improve performance of artifacts update by updating in threads.
3
+ - Added an ability to define default services
4
+
5
+ **0.6.0**
6
+ - Cleanup old image build dirs
7
+ - Add rotation to deployment log file
8
+
9
+ **0.5.10**
10
+ - Fix a regression when deployment result would not be properly returned as json.
11
+
12
+ **0.5.9**
13
+ - Added an ability to set custom user
14
+ - Allow setting environment variable in docker strategy
15
+ - Properly stop deployment if image compilation is failed
16
+
1
17
  **0.5.8**
2
18
  - Update gemspec to support ruby 2.5
3
19
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kuber_kit (0.5.8)
4
+ kuber_kit (0.6.1)
5
5
  cli-ui
6
6
  contracts-lite
7
7
  dry-auto_inject (~> 0.7.0)
data/TODO.md CHANGED
@@ -1,8 +1,3 @@
1
- - add kit get method for more interactive kubernetes
2
- - env files should use a separate deployment method (with change detection)
3
1
  - add automatical confirmation support for service deployer
4
2
  - template should be able to set default attributes
5
- - template should be able to depend on image?
6
- - cleanup image builds older than some date
7
- - add some rotation for deploy log
8
- - kit status should show the list of services and their status, with ability to select & view logs
3
+ - template should be able to depend on image?
@@ -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/lib/kuber_kit.rb CHANGED
@@ -79,6 +79,7 @@ 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'
@@ -121,7 +122,7 @@ module KuberKit
121
122
 
122
123
  module ArtifactsSync
123
124
  autoload :AbstractArtifactResolver, 'artifacts_sync/abstract_artifact_resolver'
124
- autoload :ArtifactsUpdater, 'artifacts_sync/artifacts_updater'
125
+ autoload :ArtifactUpdater, 'artifacts_sync/artifact_updater'
125
126
  autoload :GitArtifactResolver, 'artifacts_sync/git_artifact_resolver'
126
127
  autoload :NullArtifactResolver, 'artifacts_sync/null_artifact_resolver'
127
128
  end
@@ -153,6 +154,7 @@ module KuberKit
153
154
  autoload :ActionHandler, 'service_deployer/action_handler'
154
155
  autoload :StrategyDetector, 'service_deployer/strategy_detector'
155
156
  autoload :Deployer, 'service_deployer/deployer'
157
+ autoload :DeploymentOptionsSelector, 'service_deployer/deployment_options_selector'
156
158
  autoload :ServiceListResolver, 'service_deployer/service_list_resolver'
157
159
  autoload :ServiceDependencyResolver, 'service_deployer/service_dependency_resolver'
158
160
 
@@ -170,6 +172,7 @@ module KuberKit
170
172
  end
171
173
 
172
174
  module Actions
175
+ autoload :ActionResult, 'actions/action_result'
173
176
  autoload :ImageCompiler, 'actions/image_compiler'
174
177
  autoload :EnvFileReader, 'actions/env_file_reader'
175
178
  autoload :TemplateReader, 'actions/template_reader'
@@ -275,6 +278,11 @@ module KuberKit
275
278
  KuberKit::Core::ContextHelper::BaseHelper.class_exec(&proc)
276
279
  end
277
280
 
281
+ def set_user(value)
282
+ @user = value
283
+ @user_id = nil
284
+ end
285
+
278
286
  def user
279
287
  @user ||= ENV["KUBER_KIT_USERNAME"] || `whoami`.chomp
280
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
@@ -5,7 +5,7 @@ class KuberKit::Actions::ConfigurationLoader
5
5
  "core.service_store",
6
6
  "core.configuration_store",
7
7
  "tools.workdir_detector",
8
- "artifacts_sync.artifacts_updater",
8
+ "artifacts_sync.artifact_updater",
9
9
  "shell.local_shell",
10
10
  "ui",
11
11
  "configs"
@@ -43,11 +43,7 @@ class KuberKit::Actions::ConfigurationLoader
43
43
  load_infrastructure(infra_path)
44
44
 
45
45
  if load_inventory
46
- ui.create_task("Updating artifacts") do |task|
47
- artifacts = KuberKit.current_configuration.artifacts.values
48
- artifacts_updater.update(local_shell, artifacts)
49
- task.update_title("Updated #{artifacts.count} artifacts")
50
- end
46
+ update_artifacts(KuberKit.current_configuration.artifacts.values)
51
47
 
52
48
  ui.create_task("Loading image definitions") do |task|
53
49
  files = image_store.load_definitions(images_path)
@@ -101,4 +97,17 @@ class KuberKit::Actions::ConfigurationLoader
101
97
  rescue KuberKit::Shell::AbstractShell::DirNotFoundError
102
98
  ui.print_warning("ConfigurationLoader", "Directory with infrastructure not found: #{infra_path}")
103
99
  end
100
+
101
+ def update_artifacts(artifacts)
102
+ return unless artifacts.any?
103
+
104
+ artifact_task_group = ui.create_task_group
105
+ artifacts.each do |artifact|
106
+ artifact_task_group.add("Updating #{artifact.name.to_s.yellow}") do |task|
107
+ artifact_updater.update(local_shell, artifact)
108
+ task.update_title("Updated #{artifact.name.to_s.green}")
109
+ end
110
+ end
111
+ artifact_task_group.wait
112
+ end
104
113
  end
@@ -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,21 +20,24 @@ 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
-
30
+ default_services = current_configuration.default_services.map(&:to_s)
29
31
  disabled_services = current_configuration.disabled_services.map(&:to_s)
30
32
  disabled_services += skip_services if skip_services
33
+
31
34
 
32
35
  service_names = service_list_resolver.resolve(
33
36
  services: services || [],
34
37
  tags: tags || [],
35
38
  enabled_services: current_configuration.enabled_services.map(&:to_s),
36
- disabled_services: disabled_services
39
+ disabled_services: disabled_services,
40
+ default_services: default_services
37
41
  ).map(&:to_sym)
38
42
 
39
43
  # Return the list of services with all dependencies.
@@ -44,54 +48,50 @@ class KuberKit::Actions::ServiceDeployer
44
48
  return false
45
49
  end
46
50
 
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)
51
+ unless allow_deployment?(require_confirmation: require_confirmation, service_names: all_service_names)
52
+ return false
57
53
  end
58
54
 
59
- images_names = services.map(&:images).flatten.uniq
60
-
55
+ # Compile images for all services and dependencies
56
+ images_names = get_image_names(service_names: all_service_names)
61
57
  unless skip_compile
62
- compile_result = compile_images(images_names)
63
- return false unless compile_result
58
+ compilation_result = compile_images(images_names)
59
+
60
+ return false unless compilation_result && compilation_result.succeeded?
64
61
  end
65
62
 
66
- deployed_services = []
67
- deployment_result = {}
68
63
  service_dependency_resolver.each_with_deps(service_names) do |dep_service_names|
69
64
  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)
65
+
66
+ if deployment_result.succeeded?
67
+ deploy_simultaneously(dep_service_names, deployment_result)
68
+ end
73
69
  end
74
70
 
75
- { services: all_service_names, deployment: deployment_result }
71
+ deployment_result
76
72
  rescue KuberKit::Error => e
77
73
  ui.print_error("Error", e.message)
78
74
 
75
+ deployment_result.failed!(e.message)
76
+
79
77
  false
80
78
  rescue Interrupt => e
81
79
  process_cleaner.clean
80
+
81
+ false
82
82
  end
83
83
 
84
84
  private
85
- def deploy_simultaneously(service_names)
85
+ def deploy_simultaneously(service_names, deployment_result)
86
86
  task_group = ui.create_task_group
87
87
 
88
- deployer_result = {}
89
-
90
88
  service_names.each do |service_name|
91
89
 
92
90
  ui.print_debug("ServiceDeployer", "Started deploying: #{service_name.to_s.green}")
93
91
  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)
92
+ deployment_result.start_task(service_name)
93
+ service_result = service_deployer.call(local_shell, service_name.to_sym)
94
+ deployment_result.finish_task(service_name, service_result)
95
95
 
96
96
  task.update_title("Deployed #{service_name.to_s.green}")
97
97
  ui.print_debug("ServiceDeployer", "Finished deploying: #{service_name.to_s.green}")
@@ -99,55 +99,30 @@ class KuberKit::Actions::ServiceDeployer
99
99
  end
100
100
 
101
101
  task_group.wait
102
-
103
- deployer_result
104
102
  end
105
103
 
106
104
  def compile_images(images_names)
107
- return true if images_names.empty?
105
+ return KuberKit::Actions::ActionResult.new if images_names.empty?
108
106
  image_compiler.call(images_names, {})
109
107
  end
110
108
 
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]]
109
+ def get_image_names(service_names:)
110
+ services = service_names.map do |service_name|
111
+ service_store.get_service(service_name.to_sym)
134
112
  end
113
+
114
+ services.map(&:images).flatten.uniq
135
115
  end
136
116
 
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 [[], []]
117
+ def allow_deployment?(require_confirmation:, service_names:)
118
+ services_list = service_names.map(&:to_s).map(&:yellow).join(", ")
119
+ ui.print_info "ServiceDeployer", "The following services will be deployed: #{services_list}"
120
+
121
+ unless require_confirmation
122
+ return true
148
123
  end
149
124
 
150
- selected_service = ui.prompt("Please select which service to deploy", services)
151
- [[selected_service], []]
125
+ result = ui.prompt("Please confirm to continue deployment", ["confirm".green, "cancel".red])
126
+ return ["confirm".green, "confirm", "yes"].include?(result)
152
127
  end
153
128
  end
@@ -1,4 +1,4 @@
1
- class KuberKit::ArtifactsSync::ArtifactsUpdater
1
+ class KuberKit::ArtifactsSync::ArtifactUpdater
2
2
  ResolverNotFoundError = Class.new(KuberKit::NotFoundError)
3
3
 
4
4
  include KuberKit::Import[
@@ -18,18 +18,16 @@ class KuberKit::ArtifactsSync::ArtifactsUpdater
18
18
  @@resolvers[artifact_class] = artifact_resolver
19
19
  end
20
20
 
21
- def update(shell, artifacts)
21
+ def update(shell, artifact)
22
22
  add_default_resolvers
23
23
 
24
- artifacts.each do |artifact|
25
- resolver = @@resolvers[artifact.class]
24
+ resolver = @@resolvers[artifact.class]
26
25
 
27
- ui.print_debug "ArtifactUpdater", "Updating artifact #{artifact.name.to_s.green}"
28
-
29
- raise ResolverNotFoundError, "Can't find resolver for artifact #{artifact}" if resolver.nil?
26
+ ui.print_debug "ArtifactUpdater", "Updating artifact #{artifact.name.to_s.green}"
27
+
28
+ raise ResolverNotFoundError, "Can't find resolver for artifact #{artifact}" if resolver.nil?
30
29
 
31
- resolver.resolve(shell, artifact)
32
- end
30
+ resolver.resolve(shell, artifact)
33
31
  end
34
32
 
35
33
  def add_default_resolvers
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
@@ -41,10 +45,10 @@ class KuberKit::CLI < Thor
41
45
 
42
46
  if KuberKit::Container['actions.configuration_loader'].call(options)
43
47
  require_confirmation = options[:require_confirmation] ||
44
- KuberKit.current_configuration.deployer_require_confirimation ||
48
+ KuberKit.current_configuration.deployer_require_confirmation ||
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,6 +185,10 @@ 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
193
  root_path = KuberKit::Container['tools.workdir_detector'].call(options)
183
194
  config_file_path = File.join(root_path, APP_CONFIG_FILENAME)
@@ -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
@@ -213,8 +217,8 @@ class KuberKit::Container
213
217
  KuberKit::ImageCompiler::VersionTagBuilder.new
214
218
  end
215
219
 
216
- register "artifacts_sync.artifacts_updater" do
217
- KuberKit::ArtifactsSync::ArtifactsUpdater.new
220
+ register "artifacts_sync.artifact_updater" do
221
+ KuberKit::ArtifactsSync::ArtifactUpdater.new
218
222
  end
219
223
 
220
224
  register "artifacts_sync.git_artifact_resolver" do
@@ -273,6 +277,10 @@ class KuberKit::Container
273
277
  KuberKit::ServiceDeployer::Deployer.new
274
278
  end
275
279
 
280
+ register "service_deployer.deployment_options_selector" do
281
+ KuberKit::ServiceDeployer::DeploymentOptionsSelector.new
282
+ end
283
+
276
284
  register "service_deployer.service_list_resolver" do
277
285
  KuberKit::ServiceDeployer::ServiceListResolver.new
278
286
  end
@@ -1,7 +1,8 @@
1
1
  class KuberKit::Core::Configuration
2
2
  attr_reader :name, :artifacts, :registries, :env_files, :templates, :kubeconfig_path,
3
- :services_attributes, :enabled_services, :disabled_services, :build_servers, :global_build_vars,
4
- :deployer_strategy, :deployer_namespace, :deployer_require_confirimation
3
+ :services_attributes, :enabled_services, :disabled_services, :default_services,
4
+ :build_servers, :global_build_vars,
5
+ :deployer_strategy, :deployer_namespace, :deployer_require_confirmation
5
6
 
6
7
  Contract KeywordArgs[
7
8
  name: Symbol,
@@ -13,15 +14,17 @@ class KuberKit::Core::Configuration
13
14
  services_attributes: HashOf[Symbol => Hash],
14
15
  enabled_services: ArrayOf[Symbol],
15
16
  disabled_services: ArrayOf[Symbol],
17
+ default_services: ArrayOf[Symbol],
16
18
  build_servers: ArrayOf[KuberKit::Core::BuildServers::AbstractBuildServer],
17
19
  global_build_vars: HashOf[Symbol => Any],
18
20
  deployer_strategy: Symbol,
19
21
  deployer_namespace: Maybe[Symbol],
20
- deployer_require_confirimation: Bool,
22
+ deployer_require_confirmation: Bool,
21
23
  ] => Any
22
24
  def initialize(name:, artifacts:, registries:, env_files:, templates:, kubeconfig_path:,
23
- services_attributes:, enabled_services:, disabled_services:, build_servers:, global_build_vars:,
24
- deployer_strategy:, deployer_namespace:, deployer_require_confirimation:)
25
+ services_attributes:, enabled_services:, disabled_services:, default_services:,
26
+ build_servers:, global_build_vars:,
27
+ deployer_strategy:, deployer_namespace:, deployer_require_confirmation:)
25
28
  @name = name
26
29
  @artifacts = artifacts
27
30
  @registries = registries
@@ -32,10 +35,11 @@ class KuberKit::Core::Configuration
32
35
  @services_attributes = services_attributes
33
36
  @enabled_services = enabled_services
34
37
  @disabled_services = disabled_services
38
+ @default_services = default_services
35
39
  @global_build_vars = global_build_vars
36
40
  @deployer_strategy = deployer_strategy
37
41
  @deployer_namespace = deployer_namespace
38
- @deployer_require_confirimation = deployer_require_confirimation
42
+ @deployer_require_confirmation = deployer_require_confirmation
39
43
  end
40
44
 
41
45
  def service_attributes(service_name)
@@ -13,6 +13,7 @@ class KuberKit::Core::ConfigurationDefinition
13
13
  @build_servers = []
14
14
  @enabled_services = []
15
15
  @disabled_services = []
16
+ @default_services = []
16
17
  @services_attributes = {}
17
18
  end
18
19
 
@@ -26,12 +27,13 @@ class KuberKit::Core::ConfigurationDefinition
26
27
  kubeconfig_path: @kubeconfig_path,
27
28
  enabled_services: @enabled_services,
28
29
  disabled_services: @disabled_services,
30
+ default_services: @default_services,
29
31
  build_servers: @build_servers,
30
32
  services_attributes: @services_attributes,
31
33
  global_build_vars: @global_build_vars,
32
34
  deployer_strategy: @deployer_strategy,
33
35
  deployer_namespace: @deployer_namespace,
34
- deployer_require_confirimation: @deployer_require_confirimation || false,
36
+ deployer_require_confirmation: @deployer_require_confirmation || false,
35
37
  )
36
38
  end
37
39
 
@@ -97,11 +99,12 @@ class KuberKit::Core::ConfigurationDefinition
97
99
  self
98
100
  end
99
101
 
100
- def deployer_require_confirimation
101
- @deployer_require_confirimation = true
102
+ def deployer_require_confirmation
103
+ @deployer_require_confirmation = true
102
104
 
103
105
  self
104
106
  end
107
+ alias_method :deployer_require_confirimation, :deployer_require_confirmation
105
108
 
106
109
  def enabled_services(services)
107
110
  if services.is_a?(Hash)
@@ -118,6 +121,11 @@ class KuberKit::Core::ConfigurationDefinition
118
121
  raise KuberKit::Error, "#enabled_services method accepts only Array or Hash"
119
122
  end
120
123
 
124
+ def default_services(services)
125
+ @default_services += services.map(&:to_sym)
126
+ return self
127
+ end
128
+
121
129
  def disabled_services(services)
122
130
  @disabled_services += services.map(&:to_sym)
123
131
  return self
@@ -30,10 +30,11 @@ class KuberKit::Core::ConfigurationFactory
30
30
  services_attributes: configuration_attrs.services_attributes,
31
31
  enabled_services: configuration_attrs.enabled_services,
32
32
  disabled_services: configuration_attrs.disabled_services,
33
+ default_services: configuration_attrs.default_services,
33
34
  global_build_vars: configuration_attrs.global_build_vars || {},
34
35
  deployer_strategy: configuration_attrs.deployer_strategy || configs.deployer_strategy,
35
36
  deployer_namespace: configuration_attrs.deployer_namespace,
36
- deployer_require_confirimation: configuration_attrs.deployer_require_confirimation,
37
+ deployer_require_confirmation: configuration_attrs.deployer_require_confirmation,
37
38
  )
38
39
  end
39
40
 
@@ -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
@@ -7,9 +7,10 @@ class KuberKit::ServiceDeployer::ServiceListResolver
7
7
  services: Optional[ArrayOf[String]],
8
8
  tags: Optional[ArrayOf[String]],
9
9
  enabled_services: Optional[ArrayOf[String]],
10
- disabled_services: Optional[ArrayOf[String]]
10
+ disabled_services: Optional[ArrayOf[String]],
11
+ default_services: Optional[ArrayOf[String]]
11
12
  ] => ArrayOf[String]
12
- def resolve(services: [], tags: [], enabled_services: [], disabled_services: [])
13
+ def resolve(services: [], tags: [], enabled_services: [], disabled_services: [], default_services: [])
13
14
  all_definitions = service_store.all_definitions.values
14
15
 
15
16
  included_services, excluded_services = split_by_inclusion(services)
@@ -41,6 +42,10 @@ class KuberKit::ServiceDeployer::ServiceListResolver
41
42
  included_services = included_services.select{ |s| !disabled_services.include?(s) }
42
43
  end
43
44
 
45
+ if included_services.any?
46
+ included_services += default_services
47
+ end
48
+
44
49
  included_services
45
50
  end
46
51
 
@@ -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
 
@@ -1,3 +1,3 @@
1
1
  module KuberKit
2
- VERSION = "0.5.8"
2
+ VERSION = "0.6.1"
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.8
4
+ version: 0.6.1
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-17 00:00:00.000000000 Z
11
+ date: 2021-07-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: contracts-lite
@@ -198,6 +198,8 @@ files:
198
198
  - example/images/app_sources/Dockerfile
199
199
  - example/images/app_sources/build_context/source.rb
200
200
  - example/images/app_sources/image.rb
201
+ - example/images/failing_app/Dockerfile
202
+ - example/images/failing_app/image.rb
201
203
  - example/images/ruby/Dockerfile
202
204
  - example/images/ruby/image.rb
203
205
  - example/images/ruby_app/Dockerfile
@@ -214,9 +216,11 @@ files:
214
216
  - example/services/compose_app.rb
215
217
  - example/services/docker_app.rb
216
218
  - example/services/env_file.rb
219
+ - example/services/failing_app.rb
217
220
  - example/services/ruby_app.rb
218
221
  - kuber_kit.gemspec
219
222
  - lib/kuber_kit.rb
223
+ - lib/kuber_kit/actions/action_result.rb
220
224
  - lib/kuber_kit/actions/configuration_loader.rb
221
225
  - lib/kuber_kit/actions/env_file_reader.rb
222
226
  - lib/kuber_kit/actions/image_compiler.rb
@@ -232,7 +236,7 @@ files:
232
236
  - lib/kuber_kit/actions/service_reader.rb
233
237
  - lib/kuber_kit/actions/template_reader.rb
234
238
  - lib/kuber_kit/artifacts_sync/abstract_artifact_resolver.rb
235
- - lib/kuber_kit/artifacts_sync/artifacts_updater.rb
239
+ - lib/kuber_kit/artifacts_sync/artifact_updater.rb
236
240
  - lib/kuber_kit/artifacts_sync/git_artifact_resolver.rb
237
241
  - lib/kuber_kit/artifacts_sync/null_artifact_resolver.rb
238
242
  - lib/kuber_kit/cli.rb
@@ -302,6 +306,7 @@ files:
302
306
  - lib/kuber_kit/preprocessing/text_preprocessor.rb
303
307
  - lib/kuber_kit/service_deployer/action_handler.rb
304
308
  - lib/kuber_kit/service_deployer/deployer.rb
309
+ - lib/kuber_kit/service_deployer/deployment_options_selector.rb
305
310
  - lib/kuber_kit/service_deployer/service_dependency_resolver.rb
306
311
  - lib/kuber_kit/service_deployer/service_list_resolver.rb
307
312
  - lib/kuber_kit/service_deployer/strategies/abstract.rb
@@ -327,6 +332,7 @@ files:
327
332
  - lib/kuber_kit/template_reader/reader.rb
328
333
  - lib/kuber_kit/template_reader/strategies/abstract.rb
329
334
  - lib/kuber_kit/template_reader/strategies/artifact_file.rb
335
+ - lib/kuber_kit/tools/build_dir_cleaner.rb
330
336
  - lib/kuber_kit/tools/file_presence_checker.rb
331
337
  - lib/kuber_kit/tools/logger_factory.rb
332
338
  - lib/kuber_kit/tools/process_cleaner.rb