kuber_kit 0.4.7 → 0.5.2
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 +5 -0
- data/Gemfile.lock +2 -2
- data/TODO.md +7 -5
- data/example/images/ruby_app/Dockerfile +3 -1
- data/example/services/docker_app.rb +1 -1
- data/example/services/ruby_app.rb +1 -0
- data/lib/kuber_kit.rb +10 -0
- data/lib/kuber_kit/actions/kubectl_attacher.rb +2 -2
- data/lib/kuber_kit/actions/kubectl_console.rb +2 -2
- data/lib/kuber_kit/actions/kubectl_describe.rb +2 -2
- data/lib/kuber_kit/actions/kubectl_env.rb +19 -0
- data/lib/kuber_kit/actions/kubectl_logs.rb +2 -2
- data/lib/kuber_kit/actions/service_checker.rb +32 -0
- data/lib/kuber_kit/actions/service_deployer.rb +78 -59
- data/lib/kuber_kit/cli.rb +35 -0
- data/lib/kuber_kit/configs.rb +2 -1
- data/lib/kuber_kit/container.rb +24 -0
- data/lib/kuber_kit/core/dependencies/abstract_dependency_resolver.rb +75 -0
- data/lib/kuber_kit/core/image.rb +2 -1
- data/lib/kuber_kit/core/service.rb +4 -2
- data/lib/kuber_kit/core/service_definition.rb +13 -6
- data/lib/kuber_kit/core/service_factory.rb +1 -0
- data/lib/kuber_kit/image_compiler/image_dependency_resolver.rb +5 -53
- data/lib/kuber_kit/kubernetes/resource_selector.rb +33 -0
- data/lib/kuber_kit/kubernetes/resources_fetcher.rb +7 -30
- data/lib/kuber_kit/service_deployer/service_dependency_resolver.rb +14 -0
- data/lib/kuber_kit/service_deployer/strategies/docker.rb +18 -1
- data/lib/kuber_kit/service_deployer/strategies/kubernetes.rb +9 -2
- data/lib/kuber_kit/shell/commands/kubectl_commands.rb +12 -4
- data/lib/kuber_kit/shell/commands/system_commands.rb +32 -0
- data/lib/kuber_kit/shell/local_shell.rb +6 -2
- data/lib/kuber_kit/shell/ssh_shell.rb +1 -1
- data/lib/kuber_kit/tools/process_cleaner.rb +38 -0
- data/lib/kuber_kit/version.rb +1 -1
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 485e80726d7350ce239a165860ba4096b3549178d10e5ff8abdc918df983ab4c
|
4
|
+
data.tar.gz: 480a475c88bf4a6626a182ade7909e0a08143a978d96471faf0c2495021abf6a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d285c169ea188e3c8d4679db94ea74a7c3b5cabc993fbd41e675d590505d1f714836de4b052cd1b1793d810069b1d61f2520d78bcc8c538a6efaa95730f0dc2d
|
7
|
+
data.tar.gz: b645418d23a5e68f5bebf571dcd2853d460cadd42247ccc749b5c938825b08671059fedd3cbb83fd960cc3deb8a6eb0a121c11468e4dc7e365dc89b803046383
|
data/CHANGELOG.md
ADDED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
kuber_kit (0.
|
4
|
+
kuber_kit (0.5.2)
|
5
5
|
cli-ui
|
6
6
|
contracts-lite
|
7
7
|
dry-auto_inject
|
@@ -20,7 +20,7 @@ GEM
|
|
20
20
|
docile (1.3.2)
|
21
21
|
dry-auto_inject (0.7.0)
|
22
22
|
dry-container (>= 0.3.4)
|
23
|
-
dry-configurable (0.12.
|
23
|
+
dry-configurable (0.12.1)
|
24
24
|
concurrent-ruby (~> 1.0)
|
25
25
|
dry-core (~> 0.5, >= 0.5.0)
|
26
26
|
dry-container (0.7.2)
|
data/TODO.md
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
-
|
2
|
-
-
|
3
|
-
-
|
4
|
-
-
|
1
|
+
- do not show result for images list, if list is too large (Mikhail)
|
2
|
+
- add kit get method for more interactive kubernetes
|
3
|
+
- env files should use a separate deployment method (with change detection)
|
4
|
+
- add automatical confirmation support for service deployer
|
5
5
|
- template should be able to set default attributes
|
6
6
|
- template should be able to depend on image?
|
7
|
-
- cleanup image builds older than some date
|
7
|
+
- cleanup image builds older than some date
|
8
|
+
- add some rotation for deploy log
|
9
|
+
- kit status should show the list of services and their status, with ability to select & view logs
|
data/lib/kuber_kit.rb
CHANGED
@@ -46,6 +46,10 @@ module KuberKit
|
|
46
46
|
autoload :BuildServer, 'core/build_servers/build_server'
|
47
47
|
end
|
48
48
|
|
49
|
+
module Dependencies
|
50
|
+
autoload :AbstractDependencyResolver, 'core/dependencies/abstract_dependency_resolver'
|
51
|
+
end
|
52
|
+
|
49
53
|
module EnvFiles
|
50
54
|
autoload :EnvFileStore, 'core/env_files/env_file_store'
|
51
55
|
autoload :AbstractEnvFile, 'core/env_files/abstract_env_file'
|
@@ -76,6 +80,7 @@ module KuberKit
|
|
76
80
|
module Tools
|
77
81
|
autoload :FilePresenceChecker, 'tools/file_presence_checker'
|
78
82
|
autoload :LoggerFactory, 'tools/logger_factory'
|
83
|
+
autoload :ProcessCleaner, 'tools/process_cleaner'
|
79
84
|
end
|
80
85
|
|
81
86
|
module Shell
|
@@ -92,6 +97,7 @@ module KuberKit
|
|
92
97
|
autoload :GitCommands, 'shell/commands/git_commands'
|
93
98
|
autoload :RsyncCommands, 'shell/commands/rsync_commands'
|
94
99
|
autoload :KubectlCommands, 'shell/commands/kubectl_commands'
|
100
|
+
autoload :SystemCommands, 'shell/commands/system_commands'
|
95
101
|
end
|
96
102
|
end
|
97
103
|
|
@@ -143,6 +149,7 @@ module KuberKit
|
|
143
149
|
autoload :StrategyDetector, 'service_deployer/strategy_detector'
|
144
150
|
autoload :Deployer, 'service_deployer/deployer'
|
145
151
|
autoload :ServiceListResolver, 'service_deployer/service_list_resolver'
|
152
|
+
autoload :ServiceDependencyResolver, 'service_deployer/service_dependency_resolver'
|
146
153
|
|
147
154
|
module Strategies
|
148
155
|
autoload :Abstract, 'service_deployer/strategies/abstract'
|
@@ -163,12 +170,14 @@ module KuberKit
|
|
163
170
|
autoload :TemplateReader, 'actions/template_reader'
|
164
171
|
autoload :ServiceReader, 'actions/service_reader'
|
165
172
|
autoload :ServiceDeployer, 'actions/service_deployer'
|
173
|
+
autoload :ServiceChecker, 'actions/service_checker'
|
166
174
|
autoload :ConfigurationLoader, 'actions/configuration_loader'
|
167
175
|
autoload :KubectlApplier, 'actions/kubectl_applier'
|
168
176
|
autoload :KubectlAttacher, 'actions/kubectl_attacher'
|
169
177
|
autoload :KubectlConsole, 'actions/kubectl_console'
|
170
178
|
autoload :KubectlDescribe, 'actions/kubectl_describe'
|
171
179
|
autoload :KubectlLogs, 'actions/kubectl_logs'
|
180
|
+
autoload :KubectlEnv, 'actions/kubectl_env'
|
172
181
|
end
|
173
182
|
|
174
183
|
module Extensions
|
@@ -176,6 +185,7 @@ module KuberKit
|
|
176
185
|
end
|
177
186
|
|
178
187
|
module Kubernetes
|
188
|
+
autoload :ResourceSelector, 'kubernetes/resource_selector'
|
179
189
|
autoload :ResourcesFetcher, 'kubernetes/resources_fetcher'
|
180
190
|
end
|
181
191
|
|
@@ -2,7 +2,7 @@ class KuberKit::Actions::KubectlAttacher
|
|
2
2
|
include KuberKit::Import[
|
3
3
|
"shell.kubectl_commands",
|
4
4
|
"shell.local_shell",
|
5
|
-
"kubernetes.
|
5
|
+
"kubernetes.resource_selector",
|
6
6
|
"ui"
|
7
7
|
]
|
8
8
|
|
@@ -12,7 +12,7 @@ class KuberKit::Actions::KubectlAttacher
|
|
12
12
|
deployer_namespace = KuberKit.current_configuration.deployer_namespace
|
13
13
|
|
14
14
|
if !pod_name
|
15
|
-
pod_name =
|
15
|
+
pod_name = resource_selector.call("attach")
|
16
16
|
end
|
17
17
|
|
18
18
|
kubectl_commands.exec(
|
@@ -2,7 +2,7 @@ class KuberKit::Actions::KubectlConsole
|
|
2
2
|
include KuberKit::Import[
|
3
3
|
"shell.kubectl_commands",
|
4
4
|
"shell.local_shell",
|
5
|
-
"kubernetes.
|
5
|
+
"kubernetes.resource_selector",
|
6
6
|
"ui"
|
7
7
|
]
|
8
8
|
|
@@ -12,7 +12,7 @@ class KuberKit::Actions::KubectlConsole
|
|
12
12
|
deployer_namespace = KuberKit.current_configuration.deployer_namespace
|
13
13
|
|
14
14
|
if !pod_name
|
15
|
-
pod_name =
|
15
|
+
pod_name = resource_selector.call("attach")
|
16
16
|
end
|
17
17
|
|
18
18
|
kubectl_commands.exec(
|
@@ -2,7 +2,7 @@ class KuberKit::Actions::KubectlDescribe
|
|
2
2
|
include KuberKit::Import[
|
3
3
|
"shell.kubectl_commands",
|
4
4
|
"shell.local_shell",
|
5
|
-
"kubernetes.
|
5
|
+
"kubernetes.resource_selector",
|
6
6
|
"ui"
|
7
7
|
]
|
8
8
|
|
@@ -12,7 +12,7 @@ class KuberKit::Actions::KubectlDescribe
|
|
12
12
|
deployer_namespace = KuberKit.current_configuration.deployer_namespace
|
13
13
|
|
14
14
|
if !resource_name
|
15
|
-
resource_name =
|
15
|
+
resource_name = resource_selector.call("describe", include_ingresses: true, include_pods: true)
|
16
16
|
end
|
17
17
|
|
18
18
|
args = nil
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class KuberKit::Actions::KubectlEnv
|
2
|
+
include KuberKit::Import[
|
3
|
+
"shell.local_shell",
|
4
|
+
"ui"
|
5
|
+
]
|
6
|
+
|
7
|
+
Contract Hash => Any
|
8
|
+
def call(options)
|
9
|
+
configuration = KuberKit.current_configuration
|
10
|
+
kubeconfig_path = configuration.kubeconfig_path
|
11
|
+
ui.print_info("ENV", "export KUBECONFIG=#{kubeconfig_path}")
|
12
|
+
|
13
|
+
true
|
14
|
+
rescue KuberKit::Error => e
|
15
|
+
ui.print_error("Error", e.message)
|
16
|
+
|
17
|
+
false
|
18
|
+
end
|
19
|
+
end
|
@@ -2,7 +2,7 @@ class KuberKit::Actions::KubectlLogs
|
|
2
2
|
include KuberKit::Import[
|
3
3
|
"shell.kubectl_commands",
|
4
4
|
"shell.local_shell",
|
5
|
-
"kubernetes.
|
5
|
+
"kubernetes.resource_selector",
|
6
6
|
"ui"
|
7
7
|
]
|
8
8
|
|
@@ -12,7 +12,7 @@ class KuberKit::Actions::KubectlLogs
|
|
12
12
|
deployer_namespace = KuberKit.current_configuration.deployer_namespace
|
13
13
|
|
14
14
|
if !pod_name
|
15
|
-
pod_name =
|
15
|
+
pod_name = resource_selector.call("attach")
|
16
16
|
end
|
17
17
|
|
18
18
|
args = nil
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class KuberKit::Actions::ServiceChecker
|
2
|
+
include KuberKit::Import[
|
3
|
+
"kubernetes.resources_fetcher",
|
4
|
+
"shell.local_shell",
|
5
|
+
"core.service_store",
|
6
|
+
"ui",
|
7
|
+
]
|
8
|
+
|
9
|
+
Contract Hash => Any
|
10
|
+
def call(options)
|
11
|
+
services = service_store.all_definitions.values.map(&:service_name).map(&:to_s)
|
12
|
+
|
13
|
+
enabled_services = KuberKit.current_configuration.enabled_services.map(&:to_s)
|
14
|
+
if enabled_services.any?
|
15
|
+
services = services.select{ |s| enabled_services.include?(s) }
|
16
|
+
end
|
17
|
+
|
18
|
+
resources = resources_fetcher.call("deployments") + resources_fetcher.call("cronjobs")
|
19
|
+
|
20
|
+
missing_services = services.select{ |s| !resources.include?(s.gsub("_", "-")) }
|
21
|
+
|
22
|
+
ui.print_warning("Warning", "This command will only check services deployed using k8s")
|
23
|
+
|
24
|
+
ui.print_info("Missing", missing_services.inspect)
|
25
|
+
|
26
|
+
{}
|
27
|
+
rescue KuberKit::Error => e
|
28
|
+
ui.print_error("Error", e.message)
|
29
|
+
|
30
|
+
false
|
31
|
+
end
|
32
|
+
end
|
@@ -2,8 +2,11 @@ class KuberKit::Actions::ServiceDeployer
|
|
2
2
|
include KuberKit::Import[
|
3
3
|
"actions.image_compiler",
|
4
4
|
"service_deployer.service_list_resolver",
|
5
|
+
"service_deployer.service_dependency_resolver",
|
5
6
|
"core.service_store",
|
6
7
|
"shell.local_shell",
|
8
|
+
"tools.process_cleaner",
|
9
|
+
"configs",
|
7
10
|
"ui",
|
8
11
|
service_deployer: "service_deployer.action_handler",
|
9
12
|
]
|
@@ -23,14 +26,17 @@ class KuberKit::Actions::ServiceDeployer
|
|
23
26
|
services: services || [],
|
24
27
|
tags: tags || [],
|
25
28
|
enabled_services: KuberKit.current_configuration.enabled_services.map(&:to_s)
|
26
|
-
)
|
29
|
+
).map(&:to_sym)
|
27
30
|
|
28
|
-
|
31
|
+
# Return the list of services with all dependencies.
|
32
|
+
all_service_names = service_dependency_resolver.get_all(service_names)
|
33
|
+
|
34
|
+
unless all_service_names.any?
|
29
35
|
ui.print_warning "ServiceDeployer", "No service found with given options, nothing will be deployed."
|
30
36
|
return false
|
31
37
|
end
|
32
38
|
|
33
|
-
services_list =
|
39
|
+
services_list = all_service_names.map(&:to_s).map(&:yellow).join(", ")
|
34
40
|
ui.print_info "ServiceDeployer", "The following services will be deployed: #{services_list}"
|
35
41
|
|
36
42
|
if require_confirmation
|
@@ -38,7 +44,7 @@ class KuberKit::Actions::ServiceDeployer
|
|
38
44
|
return false unless ["confirm".green, "confirm", "yes"].include?(result)
|
39
45
|
end
|
40
46
|
|
41
|
-
services =
|
47
|
+
services = all_service_names.map do |service_name|
|
42
48
|
service_store.get_service(service_name.to_sym)
|
43
49
|
end
|
44
50
|
|
@@ -49,78 +55,91 @@ class KuberKit::Actions::ServiceDeployer
|
|
49
55
|
return false unless compile_result
|
50
56
|
end
|
51
57
|
|
52
|
-
|
58
|
+
deployed_services = []
|
59
|
+
deployment_result = {}
|
60
|
+
service_dependency_resolver.each_with_deps(service_names) do |dep_service_names|
|
61
|
+
ui.print_debug("ServiceDeployer", "Scheduling to compile: #{dep_service_names.inspect}. Limit: #{configs.deploy_simultaneous_limit}")
|
62
|
+
result = deploy_simultaneously(dep_service_names)
|
63
|
+
deployed_services += dep_service_names
|
64
|
+
deployment_result = deployment_result.merge(result)
|
65
|
+
end
|
53
66
|
|
54
|
-
{ services:
|
67
|
+
{ services: all_service_names, deployment: deployment_result }
|
55
68
|
rescue KuberKit::Error => e
|
56
69
|
ui.print_error("Error", e.message)
|
57
70
|
|
58
71
|
false
|
72
|
+
rescue Interrupt => e
|
73
|
+
process_cleaner.clean
|
59
74
|
end
|
60
75
|
|
61
|
-
|
62
|
-
|
76
|
+
private
|
77
|
+
def deploy_simultaneously(service_names)
|
78
|
+
task_group = ui.create_task_group
|
63
79
|
|
64
|
-
|
80
|
+
deployer_result = {}
|
65
81
|
|
66
|
-
|
82
|
+
service_names.each do |service_name|
|
67
83
|
|
68
|
-
|
69
|
-
|
70
|
-
|
84
|
+
ui.print_debug("ServiceDeployer", "Started deploying: #{service_name.to_s.green}")
|
85
|
+
task_group.add("Deploying #{service_name.to_s.yellow}") do |task|
|
86
|
+
deployer_result[service_name] = service_deployer.call(local_shell, service_name.to_sym)
|
71
87
|
|
72
|
-
|
73
|
-
|
88
|
+
task.update_title("Deployed #{service_name.to_s.green}")
|
89
|
+
ui.print_debug("ServiceDeployer", "Finished deploying: #{service_name.to_s.green}")
|
90
|
+
end
|
74
91
|
end
|
75
|
-
end
|
76
92
|
|
77
|
-
|
93
|
+
task_group.wait
|
78
94
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
def compile_images(images_names)
|
83
|
-
return true if images_names.empty?
|
84
|
-
image_compiler.call(images_names, {})
|
85
|
-
end
|
95
|
+
deployer_result
|
96
|
+
end
|
86
97
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
tags = [specific_service_option]
|
91
|
-
tags += service_store
|
92
|
-
.all_definitions
|
93
|
-
.values
|
94
|
-
.map(&:to_service_attrs)
|
95
|
-
.map(&:tags)
|
96
|
-
.flatten
|
97
|
-
.uniq
|
98
|
-
.sort
|
99
|
-
.map(&:to_s)
|
100
|
-
|
101
|
-
selected_tag = ui.prompt("Please select which tag to deploy", tags)
|
102
|
-
|
103
|
-
if selected_tag == specific_service_option
|
104
|
-
show_service_selection
|
105
|
-
else
|
106
|
-
[[], [selected_tag]]
|
98
|
+
def compile_images(images_names)
|
99
|
+
return true if images_names.empty?
|
100
|
+
image_compiler.call(images_names, {})
|
107
101
|
end
|
108
|
-
end
|
109
102
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
103
|
+
def show_tags_selection()
|
104
|
+
specific_service_option = "deploy specific service"
|
105
|
+
all_services_option = "deploy all services"
|
106
|
+
|
107
|
+
tags = [specific_service_option, all_services_option]
|
108
|
+
tags += service_store
|
109
|
+
.all_definitions
|
110
|
+
.values
|
111
|
+
.map(&:to_service_attrs)
|
112
|
+
.map(&:tags)
|
113
|
+
.flatten
|
114
|
+
.uniq
|
115
|
+
.sort
|
116
|
+
.map(&:to_s)
|
117
|
+
|
118
|
+
selected_tag = ui.prompt("Please select which tag to deploy", tags)
|
119
|
+
|
120
|
+
if selected_tag == specific_service_option
|
121
|
+
show_service_selection
|
122
|
+
elsif selected_tag == all_services_option
|
123
|
+
[["*"], []]
|
124
|
+
else
|
125
|
+
[[], [selected_tag]]
|
126
|
+
end
|
121
127
|
end
|
122
128
|
|
123
|
-
|
124
|
-
|
125
|
-
|
129
|
+
def show_service_selection()
|
130
|
+
services = service_store
|
131
|
+
.all_definitions
|
132
|
+
.values
|
133
|
+
.map(&:service_name)
|
134
|
+
.uniq
|
135
|
+
.sort
|
136
|
+
.map(&:to_s)
|
137
|
+
|
138
|
+
if services.empty?
|
139
|
+
return [[], []]
|
140
|
+
end
|
141
|
+
|
142
|
+
selected_service = ui.prompt("Please select which service to deploy", services)
|
143
|
+
[[selected_service], []]
|
144
|
+
end
|
126
145
|
end
|
data/lib/kuber_kit/cli.rb
CHANGED
@@ -86,6 +86,15 @@ class KuberKit::CLI < Thor
|
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
|
+
desc "check", "Check to make sure that all services are deployed"
|
90
|
+
def check()
|
91
|
+
setup(options)
|
92
|
+
|
93
|
+
if KuberKit::Container['actions.configuration_loader'].call(options)
|
94
|
+
KuberKit::Container['actions.service_checker'].call(options)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
89
98
|
desc "apply FILE_PATH", "Apply FILE_PATH with kubectl"
|
90
99
|
def apply(file_path)
|
91
100
|
setup(options)
|
@@ -132,6 +141,15 @@ class KuberKit::CLI < Thor
|
|
132
141
|
end
|
133
142
|
end
|
134
143
|
|
144
|
+
desc "env", "Show environment variables for given configuration"
|
145
|
+
def env()
|
146
|
+
setup(options)
|
147
|
+
|
148
|
+
if KuberKit::Container['actions.configuration_loader'].call(options.merge(load_inventory: false))
|
149
|
+
KuberKit::Container['actions.kubectl_env'].call(options)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
135
153
|
desc "version", "Print current version"
|
136
154
|
def version
|
137
155
|
puts KuberKit::VERSION
|
@@ -160,4 +178,21 @@ class KuberKit::CLI < Thor
|
|
160
178
|
def print_result(message, data = {})
|
161
179
|
KuberKit::Container['ui'].print_result(message, data)
|
162
180
|
end
|
181
|
+
|
182
|
+
def cleanup_processes
|
183
|
+
# Stop all threads
|
184
|
+
Thread.list.each do |t|
|
185
|
+
t.abort_on_exception = false
|
186
|
+
t.report_on_exception = false
|
187
|
+
Thread.kill(t) if t != Thread.current
|
188
|
+
end
|
189
|
+
|
190
|
+
# Find all system calls
|
191
|
+
child_pids_raw = `ps auxww | grep '[K]IT=#{Process.pid}' | awk '{print $2}'`
|
192
|
+
child_pids = child_pids_raw.to_s.split("\n").reject(&:empty?)
|
193
|
+
child_pids.each do |pid|
|
194
|
+
puts "Killing child process: #{pid}"
|
195
|
+
Process.kill("SIGHUP", pid.to_i)
|
196
|
+
end
|
197
|
+
end
|
163
198
|
end
|
data/lib/kuber_kit/configs.rb
CHANGED
@@ -4,7 +4,7 @@ class KuberKit::Configs
|
|
4
4
|
AVAILABLE_CONFIGS = [
|
5
5
|
:image_dockerfile_name, :image_build_context_dir, :image_tag, :docker_ignore_list, :image_compile_dir,
|
6
6
|
:kuber_kit_dirname, :kuber_kit_min_version, :images_dirname, :services_dirname, :infra_dirname, :configurations_dirname,
|
7
|
-
:artifact_clone_dir, :service_config_dir, :deployer_strategy, :compile_simultaneous_limit,
|
7
|
+
:artifact_clone_dir, :service_config_dir, :deployer_strategy, :compile_simultaneous_limit, :deploy_simultaneous_limit,
|
8
8
|
:additional_images_paths, :deprecation_warnings_disabled, :log_file_path
|
9
9
|
]
|
10
10
|
DOCKER_IGNORE_LIST = [
|
@@ -49,6 +49,7 @@ class KuberKit::Configs
|
|
49
49
|
set :service_config_dir, "/tmp/kuber_kit/services"
|
50
50
|
set :deployer_strategy, :kubernetes
|
51
51
|
set :compile_simultaneous_limit, 5
|
52
|
+
set :deploy_simultaneous_limit, 5
|
52
53
|
set :additional_images_paths, []
|
53
54
|
set :deprecation_warnings_disabled, false
|
54
55
|
set :log_file_path, "/tmp/kuber_kit.log"
|
data/lib/kuber_kit/container.rb
CHANGED
@@ -21,6 +21,10 @@ class KuberKit::Container
|
|
21
21
|
KuberKit::Actions::ServiceDeployer.new
|
22
22
|
end
|
23
23
|
|
24
|
+
register "actions.service_checker" do
|
25
|
+
KuberKit::Actions::ServiceChecker.new
|
26
|
+
end
|
27
|
+
|
24
28
|
register "actions.configuration_loader" do
|
25
29
|
KuberKit::Actions::ConfigurationLoader.new
|
26
30
|
end
|
@@ -45,6 +49,10 @@ class KuberKit::Container
|
|
45
49
|
KuberKit::Actions::KubectlLogs.new
|
46
50
|
end
|
47
51
|
|
52
|
+
register "actions.kubectl_env" do
|
53
|
+
KuberKit::Actions::KubectlEnv.new
|
54
|
+
end
|
55
|
+
|
48
56
|
register "configs" do
|
49
57
|
KuberKit::Configs.new
|
50
58
|
end
|
@@ -121,6 +129,10 @@ class KuberKit::Container
|
|
121
129
|
KuberKit::Container["tools.logger_factory"].create()
|
122
130
|
end
|
123
131
|
|
132
|
+
register "tools.process_cleaner" do
|
133
|
+
KuberKit::Tools::ProcessCleaner.new
|
134
|
+
end
|
135
|
+
|
124
136
|
register "shell.bash_commands" do
|
125
137
|
KuberKit::Shell::Commands::BashCommands.new
|
126
138
|
end
|
@@ -145,6 +157,10 @@ class KuberKit::Container
|
|
145
157
|
KuberKit::Shell::Commands::KubectlCommands.new
|
146
158
|
end
|
147
159
|
|
160
|
+
register "shell.system_commands" do
|
161
|
+
KuberKit::Shell::Commands::SystemCommands.new
|
162
|
+
end
|
163
|
+
|
148
164
|
register "shell.local_shell" do
|
149
165
|
KuberKit::Shell::LocalShell.new
|
150
166
|
end
|
@@ -241,6 +257,10 @@ class KuberKit::Container
|
|
241
257
|
KuberKit::ServiceDeployer::ServiceListResolver.new
|
242
258
|
end
|
243
259
|
|
260
|
+
register "service_deployer.service_dependency_resolver" do
|
261
|
+
KuberKit::ServiceDeployer::ServiceDependencyResolver.new
|
262
|
+
end
|
263
|
+
|
244
264
|
register "service_deployer.strategies.kubernetes" do
|
245
265
|
KuberKit::ServiceDeployer::Strategies::Kubernetes.new
|
246
266
|
end
|
@@ -261,6 +281,10 @@ class KuberKit::Container
|
|
261
281
|
KuberKit::ServiceReader::Reader.new
|
262
282
|
end
|
263
283
|
|
284
|
+
register "kubernetes.resource_selector" do
|
285
|
+
KuberKit::Kubernetes::ResourceSelector.new
|
286
|
+
end
|
287
|
+
|
264
288
|
register "kubernetes.resources_fetcher" do
|
265
289
|
KuberKit::Kubernetes::ResourcesFetcher.new
|
266
290
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
class KuberKit::Core::Dependencies::AbstractDependencyResolver
|
2
|
+
CircularDependencyError = Class.new(KuberKit::Error)
|
3
|
+
DependencyNotFoundError = Class.new(KuberKit::NotFoundError)
|
4
|
+
|
5
|
+
# Iterate over list of dependencies for items (including the items themself).
|
6
|
+
# Iteration will send the list to the callback block function
|
7
|
+
Contract Or[Symbol, ArrayOf[Symbol]], Proc => Any
|
8
|
+
def each_with_deps(item_names, &block)
|
9
|
+
resolved_dependencies = []
|
10
|
+
# Get first list of dependencies ready to resolve
|
11
|
+
next_dependencies = get_next(item_names, limit: dependency_batch_size)
|
12
|
+
|
13
|
+
# Call the block for each list of dependencies ready to resolve, then calculate the next list
|
14
|
+
while (next_dependencies - resolved_dependencies).any?
|
15
|
+
block.call(next_dependencies)
|
16
|
+
resolved_dependencies += next_dependencies
|
17
|
+
next_dependencies = get_next(item_names, resolved: resolved_dependencies, limit: dependency_batch_size)
|
18
|
+
end
|
19
|
+
|
20
|
+
(item_names - resolved_dependencies).each_slice(dependency_batch_size) do |group|
|
21
|
+
block.call(group)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns next list of dependencies ready to resolve.
|
26
|
+
# Item is not ready to resolve if it has personal dependency.
|
27
|
+
# E.g. if "A" depends on "B" and "C", "C" depends on "D", then only "B" and "D" will be returned.
|
28
|
+
Contract Or[Symbol, ArrayOf[Symbol]], KeywordArgs[
|
29
|
+
resolved: Optional[ArrayOf[Symbol]],
|
30
|
+
limit: Optional[Maybe[Num]]
|
31
|
+
] => Any
|
32
|
+
def get_next(item_names, resolved: [], limit: nil)
|
33
|
+
deps = Array(item_names).map { |i| get_recursive_deps(i) }.flatten.uniq
|
34
|
+
|
35
|
+
# Find out which dependencies are ready to resolve,
|
36
|
+
# they should not have unresolved personal dependencies
|
37
|
+
ready_to_resolve = deps.select do |dep_name|
|
38
|
+
unresolved_deps = get_deps(dep_name) - resolved
|
39
|
+
unresolved_deps.empty?
|
40
|
+
end
|
41
|
+
unresolved_deps = ready_to_resolve - resolved
|
42
|
+
unresolved_deps = unresolved_deps.take(limit) if limit
|
43
|
+
unresolved_deps
|
44
|
+
end
|
45
|
+
|
46
|
+
# Get all dependencies for items (including the items themself), without any limitations
|
47
|
+
Contract Or[Symbol, ArrayOf[Symbol]] => Any
|
48
|
+
def get_all(item_names)
|
49
|
+
deps = Array(item_names).map { |i| get_recursive_deps(i) }.flatten
|
50
|
+
(deps + item_names).uniq
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_recursive_deps(item_name, dependency_tree: [])
|
54
|
+
deps = get_deps(item_name)
|
55
|
+
|
56
|
+
if dependency_tree.include?(item_name)
|
57
|
+
raise CircularDependencyError, "Circular dependency found for #{item_name}. Dependency tree: #{dependency_tree.inspect}"
|
58
|
+
end
|
59
|
+
|
60
|
+
child_deps = []
|
61
|
+
deps.each do |i|
|
62
|
+
child_deps += get_recursive_deps(i, dependency_tree: dependency_tree + [item_name])
|
63
|
+
end
|
64
|
+
|
65
|
+
(deps + child_deps).uniq
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_deps(item_name)
|
69
|
+
raise "This method should be overriden"
|
70
|
+
end
|
71
|
+
|
72
|
+
def dependency_batch_size
|
73
|
+
raise "This method should be overriden"
|
74
|
+
end
|
75
|
+
end
|
data/lib/kuber_kit/core/image.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
class KuberKit::Core::Image
|
2
|
-
attr_reader :name, :dependencies, :registry, :dockerfile_path, :build_vars, :build_context_dir, :tag,
|
2
|
+
attr_reader :name, :dependencies, :registry, :dockerfile_path, :build_vars, :build_context_dir, :tag,
|
3
|
+
:before_build_callback, :after_build_callback
|
3
4
|
|
4
5
|
Contract KeywordArgs[
|
5
6
|
name: Symbol,
|
@@ -1,18 +1,20 @@
|
|
1
1
|
class KuberKit::Core::Service
|
2
2
|
AttributeNotSet = Class.new(Indocker::Error)
|
3
3
|
|
4
|
-
attr_reader :name, :template_name, :tags, :images, :attributes, :deployer_strategy
|
4
|
+
attr_reader :name, :dependencies, :template_name, :tags, :images, :attributes, :deployer_strategy
|
5
5
|
|
6
6
|
Contract KeywordArgs[
|
7
7
|
name: Symbol,
|
8
|
+
dependencies: ArrayOf[Symbol],
|
8
9
|
template_name: Maybe[Symbol],
|
9
10
|
tags: ArrayOf[Symbol],
|
10
11
|
images: ArrayOf[Symbol],
|
11
12
|
attributes: HashOf[Symbol => Any],
|
12
13
|
deployer_strategy: Maybe[Symbol]
|
13
14
|
] => Any
|
14
|
-
def initialize(name:, template_name:, tags:, images:, attributes:, deployer_strategy:)
|
15
|
+
def initialize(name:, dependencies:, template_name:, tags:, images:, attributes:, deployer_strategy:)
|
15
16
|
@name = name
|
17
|
+
@dependencies = dependencies
|
16
18
|
@template_name = template_name
|
17
19
|
@tags = tags
|
18
20
|
@images = images
|
@@ -1,22 +1,29 @@
|
|
1
1
|
class KuberKit::Core::ServiceDefinition
|
2
|
-
attr_reader :service_name, :template_name
|
2
|
+
attr_reader :service_name, :template_name, :dependencies
|
3
3
|
|
4
4
|
Contract Or[Symbol, String] => Any
|
5
5
|
def initialize(service_name)
|
6
6
|
@service_name = service_name.to_sym
|
7
|
+
@dependencies = []
|
7
8
|
end
|
8
9
|
|
9
10
|
def to_service_attrs
|
10
11
|
OpenStruct.new(
|
11
|
-
name:
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
name: @service_name,
|
13
|
+
dependencies: @dependencies,
|
14
|
+
template_name: get_value(@template_name),
|
15
|
+
tags: Array(get_value(@tags)).map(&:to_sym),
|
16
|
+
images: Array(get_value(@images)).map(&:to_sym),
|
17
|
+
attributes: get_value(@attributes),
|
16
18
|
deployer_strategy: get_value(@deployer_strategy),
|
17
19
|
)
|
18
20
|
end
|
19
21
|
|
22
|
+
def depends_on(*value, &block)
|
23
|
+
@dependencies = Array(value).flatten
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
20
27
|
def template(value = nil, &block)
|
21
28
|
@template_name = block_given? ? block : value
|
22
29
|
|
@@ -1,62 +1,14 @@
|
|
1
|
-
class KuberKit::ImageCompiler::ImageDependencyResolver
|
2
|
-
CircularDependencyError = Class.new(KuberKit::Error)
|
3
|
-
DependencyNotFoundError = Class.new(KuberKit::NotFoundError)
|
4
|
-
|
1
|
+
class KuberKit::ImageCompiler::ImageDependencyResolver < KuberKit::Core::Dependencies::AbstractDependencyResolver
|
5
2
|
include KuberKit::Import[
|
6
3
|
"core.image_store",
|
7
4
|
"configs"
|
8
5
|
]
|
9
|
-
|
10
|
-
Contract Or[Symbol, ArrayOf[Symbol]], Proc => Any
|
11
|
-
def each_with_deps(image_names, &block)
|
12
|
-
compile_limit = configs.compile_simultaneous_limit
|
13
|
-
|
14
|
-
resolved_dependencies = []
|
15
|
-
next_dependencies = get_next(image_names, limit: compile_limit)
|
16
|
-
|
17
|
-
while (next_dependencies - resolved_dependencies).any?
|
18
|
-
block.call(next_dependencies)
|
19
|
-
resolved_dependencies += next_dependencies
|
20
|
-
next_dependencies = get_next(image_names, resolved: resolved_dependencies, limit: compile_limit)
|
21
|
-
end
|
22
|
-
|
23
|
-
(image_names - resolved_dependencies).each_slice(compile_limit) do |group|
|
24
|
-
block.call(group)
|
25
|
-
end
|
26
|
-
end
|
27
6
|
|
28
|
-
Contract Or[Symbol, ArrayOf[Symbol]], KeywordArgs[
|
29
|
-
resolved: Optional[ArrayOf[Symbol]],
|
30
|
-
limit: Optional[Maybe[Num]]
|
31
|
-
] => Any
|
32
|
-
def get_next(image_names, resolved: [], limit: nil)
|
33
|
-
deps = Array(image_names).map { |i| get_recursive_deps(i) }.flatten.uniq
|
34
|
-
|
35
|
-
ready_to_resolve = deps.select do |dep_name|
|
36
|
-
unresolved_deps = get_deps(dep_name) - resolved
|
37
|
-
unresolved_deps.empty?
|
38
|
-
end
|
39
|
-
unresolved_deps = ready_to_resolve - resolved
|
40
|
-
unresolved_deps = unresolved_deps.take(limit) if limit
|
41
|
-
unresolved_deps
|
42
|
-
end
|
43
|
-
|
44
|
-
def get_recursive_deps(image_name, dependency_tree: [])
|
45
|
-
deps = get_deps(image_name)
|
46
|
-
|
47
|
-
if dependency_tree.include?(image_name)
|
48
|
-
raise CircularDependencyError, "Circular dependency found for #{image_name}. Dependency tree: #{dependency_tree.inspect}"
|
49
|
-
end
|
50
|
-
|
51
|
-
child_deps = []
|
52
|
-
deps.each do |i|
|
53
|
-
child_deps += get_recursive_deps(i, dependency_tree: dependency_tree + [image_name])
|
54
|
-
end
|
55
|
-
|
56
|
-
(deps + child_deps).uniq
|
57
|
-
end
|
58
|
-
|
59
7
|
def get_deps(image_name)
|
60
8
|
image_store.get_definition(image_name).dependencies
|
61
9
|
end
|
10
|
+
|
11
|
+
def dependency_batch_size
|
12
|
+
configs.compile_simultaneous_limit
|
13
|
+
end
|
62
14
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class KuberKit::Kubernetes::ResourceSelector
|
2
|
+
include KuberKit::Import[
|
3
|
+
"kubernetes.resources_fetcher",
|
4
|
+
"shell.local_shell",
|
5
|
+
"ui"
|
6
|
+
]
|
7
|
+
|
8
|
+
Contract String, KeywordArgs[
|
9
|
+
include_ingresses: Optional[Bool],
|
10
|
+
include_pods: Optional[Bool]
|
11
|
+
] => Any
|
12
|
+
def call(action_name, include_ingresses: false, include_pods: false)
|
13
|
+
deployments = resources_fetcher.call("deployments")
|
14
|
+
options = deployments.map{|d| "deploy/#{d}" }
|
15
|
+
options << "ingresses" if include_ingresses
|
16
|
+
options << "pods" if include_pods
|
17
|
+
option = ui.prompt("Please select resource to #{action_name}", options)
|
18
|
+
|
19
|
+
if option == "ingresses" && include_ingresses
|
20
|
+
ingresses = resources_fetcher.call("ingresses")
|
21
|
+
options = ingresses.map{|d| "ingresses/#{d}" }
|
22
|
+
return ui.prompt("Please select ingress to #{action_name}", options)
|
23
|
+
end
|
24
|
+
|
25
|
+
if option == "pods" && include_pods
|
26
|
+
ingresses = resources_fetcher.call("pods")
|
27
|
+
options = ingresses.map{|d| "pods/#{d}" }
|
28
|
+
return ui.prompt("Please select pod to #{action_name}", options)
|
29
|
+
end
|
30
|
+
|
31
|
+
option
|
32
|
+
end
|
33
|
+
end
|
@@ -2,40 +2,17 @@ class KuberKit::Kubernetes::ResourcesFetcher
|
|
2
2
|
include KuberKit::Import[
|
3
3
|
"shell.kubectl_commands",
|
4
4
|
"shell.local_shell",
|
5
|
-
"ui"
|
6
5
|
]
|
7
6
|
|
8
|
-
Contract String
|
9
|
-
|
10
|
-
|
11
|
-
] => Any
|
12
|
-
def call(action_name, include_ingresses: false, include_pods: false)
|
13
|
-
deployments = get_resources("deployments")
|
14
|
-
options = deployments.split(" ").map{|d| "deploy/#{d}" }
|
15
|
-
options << "ingresses" if include_ingresses
|
16
|
-
options << "pods" if include_pods
|
17
|
-
option = ui.prompt("Please select resource to #{action_name}", options)
|
18
|
-
|
19
|
-
if option == "ingresses" && include_ingresses
|
20
|
-
ingresses = get_resources("ingresses")
|
21
|
-
options = ingresses.split(" ").map{|d| "ingresses/#{d}" }
|
22
|
-
return ui.prompt("Please select ingress to #{action_name}", options)
|
23
|
-
end
|
24
|
-
|
25
|
-
if option == "pods" && include_pods
|
26
|
-
ingresses = get_resources("pods")
|
27
|
-
options = ingresses.split(" ").map{|d| "pods/#{d}" }
|
28
|
-
return ui.prompt("Please select pod to #{action_name}", options)
|
29
|
-
end
|
7
|
+
Contract String => ArrayOf[String]
|
8
|
+
def call(resource_type)
|
9
|
+
current_configuration = KuberKit.current_configuration
|
30
10
|
|
31
|
-
option
|
32
|
-
end
|
33
|
-
|
34
|
-
def get_resources(type)
|
35
11
|
kubectl_commands.get_resources(
|
36
|
-
local_shell,
|
37
|
-
jsonpath:
|
38
|
-
|
12
|
+
local_shell, resource_type,
|
13
|
+
jsonpath: ".items[*].metadata.name",
|
14
|
+
kubeconfig_path: current_configuration.kubeconfig_path,
|
15
|
+
namespace: current_configuration.deployer_namespace
|
39
16
|
)
|
40
17
|
end
|
41
18
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class KuberKit::ServiceDeployer::ServiceDependencyResolver < KuberKit::Core::Dependencies::AbstractDependencyResolver
|
2
|
+
include KuberKit::Import[
|
3
|
+
"core.service_store",
|
4
|
+
"configs"
|
5
|
+
]
|
6
|
+
|
7
|
+
def get_deps(service_name)
|
8
|
+
service_store.get_definition(service_name).dependencies
|
9
|
+
end
|
10
|
+
|
11
|
+
def dependency_batch_size
|
12
|
+
configs.deploy_simultaneous_limit
|
13
|
+
end
|
14
|
+
end
|
@@ -6,7 +6,9 @@ class KuberKit::ServiceDeployer::Strategies::Docker < KuberKit::ServiceDeployer:
|
|
6
6
|
]
|
7
7
|
|
8
8
|
STRATEGY_OPTIONS = [
|
9
|
+
:namespace,
|
9
10
|
:container_name,
|
11
|
+
:env_file,
|
10
12
|
:image_name,
|
11
13
|
:detached,
|
12
14
|
:command_name,
|
@@ -14,6 +16,8 @@ class KuberKit::ServiceDeployer::Strategies::Docker < KuberKit::ServiceDeployer:
|
|
14
16
|
:delete_if_exists,
|
15
17
|
:volumes,
|
16
18
|
:networks,
|
19
|
+
:expose,
|
20
|
+
:publish,
|
17
21
|
]
|
18
22
|
|
19
23
|
Contract KuberKit::Shell::AbstractShell, KuberKit::Core::Service => Any
|
@@ -24,11 +28,15 @@ class KuberKit::ServiceDeployer::Strategies::Docker < KuberKit::ServiceDeployer:
|
|
24
28
|
raise KuberKit::Error, "Unknow options for deploy strategy: #{unknown_options}. Available options: #{STRATEGY_OPTIONS}"
|
25
29
|
end
|
26
30
|
|
27
|
-
|
31
|
+
namespace = strategy_options.fetch(:namespace, nil)
|
32
|
+
container_name = strategy_options.fetch(:container_name, [namespace, service.name].compact.join("_"))
|
28
33
|
command_name = strategy_options.fetch(:command_name, nil)
|
34
|
+
env_file = strategy_options.fetch(:env_file, nil)
|
29
35
|
custom_args = strategy_options.fetch(:custom_args, nil)
|
30
36
|
networks = strategy_options.fetch(:networks, [])
|
31
37
|
volumes = strategy_options.fetch(:volumes, [])
|
38
|
+
expose_ports = strategy_options.fetch(:expose, [])
|
39
|
+
publish_ports = strategy_options.fetch(:publish, [])
|
32
40
|
hostname = strategy_options.fetch(:hostname, container_name)
|
33
41
|
|
34
42
|
image_name = strategy_options.fetch(:image_name, nil)
|
@@ -46,6 +54,9 @@ class KuberKit::ServiceDeployer::Strategies::Docker < KuberKit::ServiceDeployer:
|
|
46
54
|
if container_name
|
47
55
|
custom_args << "--name #{container_name}"
|
48
56
|
end
|
57
|
+
if env_file
|
58
|
+
custom_args << "--env-file #{env_file}"
|
59
|
+
end
|
49
60
|
if hostname
|
50
61
|
custom_args << "--hostname #{hostname}"
|
51
62
|
end
|
@@ -58,6 +69,12 @@ class KuberKit::ServiceDeployer::Strategies::Docker < KuberKit::ServiceDeployer:
|
|
58
69
|
docker_commands.create_volume(shell, volume_name) unless volume_name.start_with?("/")
|
59
70
|
custom_args << "--volume #{volume}"
|
60
71
|
end
|
72
|
+
Array(expose_ports).each do |expose_port|
|
73
|
+
custom_args << "--expose #{expose_port}"
|
74
|
+
end
|
75
|
+
Array(publish_ports).each do |publish_port|
|
76
|
+
custom_args << "--publish #{publish_port}"
|
77
|
+
end
|
61
78
|
|
62
79
|
docker_commands.run(
|
63
80
|
shell, image.remote_registry_url,
|
@@ -9,7 +9,8 @@ class KuberKit::ServiceDeployer::Strategies::Kubernetes < KuberKit::ServiceDeplo
|
|
9
9
|
:resource_type,
|
10
10
|
:resource_name,
|
11
11
|
:delete_if_exists,
|
12
|
-
:restart_if_exists
|
12
|
+
:restart_if_exists,
|
13
|
+
:wait_for_rollout
|
13
14
|
]
|
14
15
|
|
15
16
|
Contract KuberKit::Shell::AbstractShell, KuberKit::Core::Service => Any
|
@@ -41,12 +42,18 @@ class KuberKit::ServiceDeployer::Strategies::Kubernetes < KuberKit::ServiceDeplo
|
|
41
42
|
|
42
43
|
apply_result = kubectl_commands.apply_file(shell, config_path, kubeconfig_path: kubeconfig_path, namespace: namespace)
|
43
44
|
|
44
|
-
restart_enabled
|
45
|
+
restart_enabled = strategy_options.fetch(:restart_if_exists, true)
|
46
|
+
wait_for_rollout = strategy_options.fetch(:wait_for_rollout, true)
|
45
47
|
if restart_enabled && resource_exists
|
46
48
|
kubectl_commands.rolling_restart(
|
47
49
|
shell, resource_type, resource_name,
|
48
50
|
kubeconfig_path: kubeconfig_path, namespace: namespace
|
49
51
|
)
|
52
|
+
|
53
|
+
kubectl_commands.rollout_status(
|
54
|
+
shell, resource_type, resource_name, wait: true,
|
55
|
+
kubeconfig_path: kubeconfig_path, namespace: namespace
|
56
|
+
) if wait_for_rollout
|
50
57
|
end
|
51
58
|
|
52
59
|
apply_result
|
@@ -60,19 +60,19 @@ class KuberKit::Shell::Commands::KubectlCommands
|
|
60
60
|
command_parts << "-o jsonpath='{#{jsonpath}}'"
|
61
61
|
end
|
62
62
|
|
63
|
-
result = kubectl_run(shell, command_parts, kubeconfig_path: kubeconfig_path, namespace: namespace)
|
63
|
+
result = kubectl_run(shell, command_parts, kubeconfig_path: kubeconfig_path, namespace: namespace).to_s
|
64
64
|
|
65
65
|
# Hide warnings manually, until appropriate kubectl option will be available
|
66
|
-
result = result.split("\n").reject{|n| n.start_with?("Warning:") }.join("\n")
|
66
|
+
result = result.split("\n").reject{|n| n.start_with?("Warning:") }.join("\n")
|
67
67
|
|
68
|
-
result
|
68
|
+
Array(result.split(" ")).reject(&:empty?)
|
69
69
|
end
|
70
70
|
|
71
71
|
def resource_exists?(shell, resource_type, resource_name, kubeconfig_path: nil, namespace: nil)
|
72
72
|
result = get_resources(shell, resource_type,
|
73
73
|
field_selector: "metadata.name=#{resource_name}", kubeconfig_path: kubeconfig_path, namespace: namespace
|
74
74
|
)
|
75
|
-
result
|
75
|
+
result.any?
|
76
76
|
end
|
77
77
|
|
78
78
|
def delete_resource(shell, resource_type, resource_name, kubeconfig_path: nil, namespace: nil)
|
@@ -102,4 +102,12 @@ class KuberKit::Shell::Commands::KubectlCommands
|
|
102
102
|
}
|
103
103
|
}, kubeconfig_path: kubeconfig_path, namespace: namespace)
|
104
104
|
end
|
105
|
+
|
106
|
+
def rollout_status(shell, resource_type, resource_name, wait: true, kubeconfig_path: nil, namespace: nil)
|
107
|
+
command_parts = []
|
108
|
+
command_parts << %Q{rollout status #{resource_type} #{resource_name}}
|
109
|
+
command_parts << "-w" if wait
|
110
|
+
|
111
|
+
kubectl_run(shell, command_parts, kubeconfig_path: kubeconfig_path, namespace: namespace)
|
112
|
+
end
|
105
113
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class KuberKit::Shell::Commands::SystemCommands
|
2
|
+
def kill_process(shell, pid)
|
3
|
+
# we need to use kill command directly sometimes,
|
4
|
+
# because Process.kill doesn't kill processes created by system() call
|
5
|
+
shell.exec!("kill -9 #{pid}")
|
6
|
+
true
|
7
|
+
rescue
|
8
|
+
false
|
9
|
+
end
|
10
|
+
|
11
|
+
def find_pids_by_name(shell, name)
|
12
|
+
shell
|
13
|
+
.exec!("ps auxww | grep '#{name}' | grep -v 'grep' | awk '{print $2}'")
|
14
|
+
.split("\n")
|
15
|
+
.reject(&:empty?)
|
16
|
+
.map(&:chomp)
|
17
|
+
.map(&:to_i)
|
18
|
+
rescue
|
19
|
+
[]
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_child_pids(shell, pid)
|
23
|
+
shell
|
24
|
+
.exec!("pgrep -P #{pid}")
|
25
|
+
.split("\n")
|
26
|
+
.reject(&:empty?)
|
27
|
+
.map(&:chomp)
|
28
|
+
.map(&:to_i)
|
29
|
+
rescue
|
30
|
+
[]
|
31
|
+
end
|
32
|
+
end
|
@@ -15,7 +15,7 @@ class KuberKit::Shell::LocalShell < KuberKit::Shell::AbstractShell
|
|
15
15
|
end
|
16
16
|
|
17
17
|
result = nil
|
18
|
-
IO.popen(command, err: [:child, :out]) do |io|
|
18
|
+
IO.popen(wrap_command_with_pid(command), err: [:child, :out]) do |io|
|
19
19
|
result = io.read.chomp.strip
|
20
20
|
end
|
21
21
|
|
@@ -37,7 +37,7 @@ class KuberKit::Shell::LocalShell < KuberKit::Shell::AbstractShell
|
|
37
37
|
ui.print_debug("LocalShell", "Interactive: [#{command_number}]: #{command.to_s.cyan}")
|
38
38
|
end
|
39
39
|
|
40
|
-
result = system(command)
|
40
|
+
result = system(wrap_command_with_pid(command))
|
41
41
|
|
42
42
|
if !$?.success?
|
43
43
|
raise ShellError, "Shell command failed: #{command}\r\n#{result}"
|
@@ -86,6 +86,10 @@ class KuberKit::Shell::LocalShell < KuberKit::Shell::AbstractShell
|
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
|
+
def wrap_command_with_pid(command)
|
90
|
+
"KIT=#{Process.pid} #{command}"
|
91
|
+
end
|
92
|
+
|
89
93
|
private
|
90
94
|
def ensure_directory_exists(file_path)
|
91
95
|
dir_path = File.dirname(file_path)
|
@@ -27,7 +27,7 @@ class KuberKit::Shell::SshShell < KuberKit::Shell::LocalShell
|
|
27
27
|
ui.print_debug("SshShell", "#{ssh_session.host.green} > Execute: [#{command_number}]: #{command.to_s.cyan}")
|
28
28
|
end
|
29
29
|
|
30
|
-
result = ssh_session.exec!(command)
|
30
|
+
result = ssh_session.exec!(wrap_command_with_pid(command))
|
31
31
|
|
32
32
|
if result && result != "" && log_command
|
33
33
|
ui.print_debug("SshShell", "#{ssh_session.host.green} > Finished [#{command_number}] with result: \n#{result.grey}")
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class KuberKit::Tools::ProcessCleaner
|
2
|
+
include KuberKit::Import[
|
3
|
+
"shell.system_commands",
|
4
|
+
"shell.local_shell"
|
5
|
+
]
|
6
|
+
|
7
|
+
def clean
|
8
|
+
stop_threads
|
9
|
+
stop_child_proceses
|
10
|
+
end
|
11
|
+
|
12
|
+
def stop_threads
|
13
|
+
Thread.list.each do |t|
|
14
|
+
t.abort_on_exception = false
|
15
|
+
t.report_on_exception = false
|
16
|
+
Thread.kill(t) if t != Thread.current
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def stop_child_proceses
|
21
|
+
find_all_child_processes.each do |pid|
|
22
|
+
system_commands.kill_process(local_shell, pid)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def find_all_child_processes
|
29
|
+
pids = system_commands.find_pids_by_name(local_shell, "KIT=#{Process.pid}")
|
30
|
+
pids + get_child_pids(pids)
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_child_pids(pids)
|
34
|
+
pids
|
35
|
+
.map{ |p| system_commands.get_child_pids(local_shell, p) }
|
36
|
+
.flatten
|
37
|
+
end
|
38
|
+
end
|
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.5.2
|
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-03-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: contracts-lite
|
@@ -165,6 +165,7 @@ files:
|
|
165
165
|
- ".ruby-gemset"
|
166
166
|
- ".ruby-version"
|
167
167
|
- ".travis.yml"
|
168
|
+
- CHANGELOG.md
|
168
169
|
- Gemfile
|
169
170
|
- Gemfile.lock
|
170
171
|
- LICENSE.txt
|
@@ -209,7 +210,9 @@ files:
|
|
209
210
|
- lib/kuber_kit/actions/kubectl_attacher.rb
|
210
211
|
- lib/kuber_kit/actions/kubectl_console.rb
|
211
212
|
- lib/kuber_kit/actions/kubectl_describe.rb
|
213
|
+
- lib/kuber_kit/actions/kubectl_env.rb
|
212
214
|
- lib/kuber_kit/actions/kubectl_logs.rb
|
215
|
+
- lib/kuber_kit/actions/service_checker.rb
|
213
216
|
- lib/kuber_kit/actions/service_deployer.rb
|
214
217
|
- lib/kuber_kit/actions/service_reader.rb
|
215
218
|
- lib/kuber_kit/actions/template_reader.rb
|
@@ -237,6 +240,7 @@ files:
|
|
237
240
|
- lib/kuber_kit/core/context_helper/context_vars.rb
|
238
241
|
- lib/kuber_kit/core/context_helper/image_helper.rb
|
239
242
|
- lib/kuber_kit/core/context_helper/service_helper.rb
|
243
|
+
- lib/kuber_kit/core/dependencies/abstract_dependency_resolver.rb
|
240
244
|
- lib/kuber_kit/core/env_files/abstract_env_file.rb
|
241
245
|
- lib/kuber_kit/core/env_files/artifact_file.rb
|
242
246
|
- lib/kuber_kit/core/env_files/env_file_store.rb
|
@@ -273,11 +277,13 @@ files:
|
|
273
277
|
- lib/kuber_kit/image_compiler/image_builder.rb
|
274
278
|
- lib/kuber_kit/image_compiler/image_dependency_resolver.rb
|
275
279
|
- lib/kuber_kit/image_compiler/version_tag_builder.rb
|
280
|
+
- lib/kuber_kit/kubernetes/resource_selector.rb
|
276
281
|
- lib/kuber_kit/kubernetes/resources_fetcher.rb
|
277
282
|
- lib/kuber_kit/preprocessing/file_preprocessor.rb
|
278
283
|
- lib/kuber_kit/preprocessing/text_preprocessor.rb
|
279
284
|
- lib/kuber_kit/service_deployer/action_handler.rb
|
280
285
|
- lib/kuber_kit/service_deployer/deployer.rb
|
286
|
+
- lib/kuber_kit/service_deployer/service_dependency_resolver.rb
|
281
287
|
- lib/kuber_kit/service_deployer/service_list_resolver.rb
|
282
288
|
- lib/kuber_kit/service_deployer/strategies/abstract.rb
|
283
289
|
- lib/kuber_kit/service_deployer/strategies/docker.rb
|
@@ -294,6 +300,7 @@ files:
|
|
294
300
|
- lib/kuber_kit/shell/commands/git_commands.rb
|
295
301
|
- lib/kuber_kit/shell/commands/kubectl_commands.rb
|
296
302
|
- lib/kuber_kit/shell/commands/rsync_commands.rb
|
303
|
+
- lib/kuber_kit/shell/commands/system_commands.rb
|
297
304
|
- lib/kuber_kit/shell/local_shell.rb
|
298
305
|
- lib/kuber_kit/shell/ssh_session.rb
|
299
306
|
- lib/kuber_kit/shell/ssh_shell.rb
|
@@ -303,6 +310,7 @@ files:
|
|
303
310
|
- lib/kuber_kit/template_reader/strategies/artifact_file.rb
|
304
311
|
- lib/kuber_kit/tools/file_presence_checker.rb
|
305
312
|
- lib/kuber_kit/tools/logger_factory.rb
|
313
|
+
- lib/kuber_kit/tools/process_cleaner.rb
|
306
314
|
- lib/kuber_kit/ui.rb
|
307
315
|
- lib/kuber_kit/ui/api.rb
|
308
316
|
- lib/kuber_kit/ui/debug.rb
|