kuber_kit 0.5.8 → 0.6.1
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 +4 -4
- data/CHANGELOG.md +16 -0
- data/Gemfile.lock +1 -1
- data/TODO.md +1 -6
- data/example/app_data/service.yml +2 -1
- data/example/images/failing_app/Dockerfile +5 -0
- data/example/images/failing_app/image.rb +4 -0
- data/example/services/failing_app.rb +6 -0
- data/lib/kuber_kit.rb +9 -1
- data/lib/kuber_kit/actions/action_result.rb +32 -0
- data/lib/kuber_kit/actions/configuration_loader.rb +15 -6
- data/lib/kuber_kit/actions/image_compiler.rb +18 -12
- data/lib/kuber_kit/actions/service_deployer.rb +41 -66
- data/lib/kuber_kit/artifacts_sync/{artifacts_updater.rb → artifact_updater.rb} +7 -9
- data/lib/kuber_kit/cli.rb +18 -24
- data/lib/kuber_kit/container.rb +10 -2
- data/lib/kuber_kit/core/configuration.rb +10 -6
- data/lib/kuber_kit/core/configuration_definition.rb +11 -3
- data/lib/kuber_kit/core/configuration_factory.rb +2 -1
- data/lib/kuber_kit/image_compiler/action_handler.rb +3 -0
- data/lib/kuber_kit/service_deployer/deployment_options_selector.rb +49 -0
- data/lib/kuber_kit/service_deployer/service_list_resolver.rb +7 -2
- data/lib/kuber_kit/service_deployer/strategies/docker.rb +6 -1
- data/lib/kuber_kit/shell/local_shell.rb +12 -0
- data/lib/kuber_kit/tools/build_dir_cleaner.rb +26 -0
- data/lib/kuber_kit/tools/logger_factory.rb +6 -5
- data/lib/kuber_kit/version.rb +1 -1
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03c60b8fd02854d59ccad27ac3e512b726049d55f87f41d9c0ac0256344705ba
|
4
|
+
data.tar.gz: e60f2f47da61e2b5c3942878c19c863c2537bd5a6513476bb4a26aea81259674
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
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?
|
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 :
|
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.
|
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
|
-
|
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
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
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
|
-
|
43
|
-
|
44
|
-
|
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
|
-
|
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 =
|
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
|
-
|
48
|
-
|
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
|
-
|
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
|
-
|
63
|
-
|
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
|
-
|
71
|
-
|
72
|
-
|
65
|
+
|
66
|
+
if deployment_result.succeeded?
|
67
|
+
deploy_simultaneously(dep_service_names, deployment_result)
|
68
|
+
end
|
73
69
|
end
|
74
70
|
|
75
|
-
|
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
|
-
|
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
|
105
|
+
return KuberKit::Actions::ActionResult.new if images_names.empty?
|
108
106
|
image_compiler.call(images_names, {})
|
109
107
|
end
|
110
108
|
|
111
|
-
def
|
112
|
-
|
113
|
-
|
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
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
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
|
-
|
151
|
-
[
|
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::
|
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,
|
21
|
+
def update(shell, artifact)
|
22
22
|
add_default_resolvers
|
23
23
|
|
24
|
-
|
25
|
-
resolver = @@resolvers[artifact.class]
|
24
|
+
resolver = @@resolvers[artifact.class]
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
-
|
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
|
-
|
23
|
+
action_result = KuberKit::Container['actions.image_compiler'].call(image_names, options)
|
23
24
|
end
|
24
25
|
|
25
|
-
if
|
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:
|
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.
|
48
|
+
KuberKit.current_configuration.deployer_require_confirmation ||
|
45
49
|
false
|
46
50
|
started_at = Time.now.to_i
|
47
|
-
|
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
|
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:
|
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
|
data/lib/kuber_kit/container.rb
CHANGED
@@ -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.
|
217
|
-
KuberKit::ArtifactsSync::
|
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, :
|
4
|
-
:
|
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
|
-
|
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:,
|
24
|
-
|
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
|
-
@
|
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
|
-
|
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
|
101
|
-
@
|
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
|
-
|
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(
|
18
|
-
|
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(
|
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
|
|
data/lib/kuber_kit/version.rb
CHANGED
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.
|
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-
|
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/
|
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
|