kuber_kit 0.4.5 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dfc1d29b7283361acaed01c9ddd08a29d121020c75af2d6ec7e4245d347021fb
4
- data.tar.gz: 7e9063497954963223629beaa6d6ec914851c5e8c9633fa35d50986a95149aec
3
+ metadata.gz: da99b8b516e2fa2eb9090dc78084bc4b3d40f6d5856e4d3ecbbb993b1cbdef5d
4
+ data.tar.gz: 73c76c08809d116b0c5f317959b45e5fb513b518592f791d8a0d32a185a5d88c
5
5
  SHA512:
6
- metadata.gz: d0dd8904d21b8ca6648111856a6a5d8b4b3d1950a5db786f108f2906bdfc2388c6f515b4d833ce87f30f3c5098ebd1807aa0e3ef832903a4bec180b66788f3dc
7
- data.tar.gz: b9cb8446b31460a27571b8a91defbf7882ff0ecf1d8d97dd581edaa496d2f60dae58b4bd8bd6fad091c5448a16830cee48259821751211e4e6751d2128d88fe2
6
+ metadata.gz: 5953d83da7b07ebe1ee9be3ee803c6662c2a585bbc4b01a66ba9eb3232df86f11c6f9991e3e6ffd992828d25b5b9fc554bdb71ecd396026941b78f23448acb80
7
+ data.tar.gz: a36e8746b7caddea4fe4342df5be1bd7c5304856a613e42b805b119013b9f31cc40c5de9be8587b2f13850f8bc9aa1e1e0179f88904d9ec1b0d3617285261a9b
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kuber_kit (0.4.5)
4
+ kuber_kit (0.5.0)
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.0)
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,8 @@
1
+ - do not show result for images list, if list is too large (Mikhail)
1
2
  - add kit get method for interactive kubernetes
2
- - do not show result for images list, if list is too large
3
3
  - kit status should show the list of services and their status, with ability to select & view logs
4
4
  - find a way to always deploy some service, e.g. for migrations and env_files
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
@@ -2,5 +2,5 @@ KuberKit
2
2
  .define_configuration(:review)
3
3
  .use_registry(:review_default, as: :default)
4
4
  .use_artifact(:kuber_kit_repo, as: :kuber_kit_repo)
5
- .deployer_require_confirimation
5
+ #.deployer_require_confirimation
6
6
  #.use_build_server(:remote_bs)
@@ -8,4 +8,6 @@ COPY README.md README.md
8
8
 
9
9
  RUN ruby /app/source.rb
10
10
 
11
- COPY example_file.txt <%= build_vars.example_file_name %>
11
+ COPY example_file.txt <%= build_vars.example_file_name %>
12
+
13
+ CMD ["tail", "-f", "/dev/null"]
@@ -1,5 +1,5 @@
1
1
  KuberKit
2
- .define_service(:compose_app)
2
+ .define_service(:auth_app)
3
3
  .template(:docker_compose)
4
4
  .images(:ruby_app)
5
5
  .tags(:compose)
@@ -4,7 +4,7 @@ KuberKit
4
4
  .deployer_strategy(:docker)
5
5
  .attributes(
6
6
  deployer: {
7
- detached: true,
7
+ detached: false,
8
8
  image_name: :ruby_app,
9
9
  container_name: "test_docker_app",
10
10
  delete_if_exists: true
data/lib/kuber_kit.rb CHANGED
@@ -76,6 +76,7 @@ module KuberKit
76
76
  module Tools
77
77
  autoload :FilePresenceChecker, 'tools/file_presence_checker'
78
78
  autoload :LoggerFactory, 'tools/logger_factory'
79
+ autoload :ProcessCleaner, 'tools/process_cleaner'
79
80
  end
80
81
 
81
82
  module Shell
@@ -92,6 +93,7 @@ module KuberKit
92
93
  autoload :GitCommands, 'shell/commands/git_commands'
93
94
  autoload :RsyncCommands, 'shell/commands/rsync_commands'
94
95
  autoload :KubectlCommands, 'shell/commands/kubectl_commands'
96
+ autoload :SystemCommands, 'shell/commands/system_commands'
95
97
  end
96
98
  end
97
99
 
@@ -163,18 +165,25 @@ module KuberKit
163
165
  autoload :TemplateReader, 'actions/template_reader'
164
166
  autoload :ServiceReader, 'actions/service_reader'
165
167
  autoload :ServiceDeployer, 'actions/service_deployer'
168
+ autoload :ServiceChecker, 'actions/service_checker'
166
169
  autoload :ConfigurationLoader, 'actions/configuration_loader'
167
170
  autoload :KubectlApplier, 'actions/kubectl_applier'
168
171
  autoload :KubectlAttacher, 'actions/kubectl_attacher'
169
172
  autoload :KubectlConsole, 'actions/kubectl_console'
170
173
  autoload :KubectlDescribe, 'actions/kubectl_describe'
171
174
  autoload :KubectlLogs, 'actions/kubectl_logs'
175
+ autoload :KubectlEnv, 'actions/kubectl_env'
172
176
  end
173
177
 
174
178
  module Extensions
175
179
  autoload :Inspectable, 'extensions/inspectable'
176
180
  end
177
181
 
182
+ module Kubernetes
183
+ autoload :ResourceSelector, 'kubernetes/resource_selector'
184
+ autoload :ResourcesFetcher, 'kubernetes/resources_fetcher'
185
+ end
186
+
178
187
  module UI
179
188
  autoload :Interactive, 'ui/interactive'
180
189
  autoload :Simple, 'ui/simple'
@@ -2,6 +2,7 @@ class KuberKit::Actions::KubectlAttacher
2
2
  include KuberKit::Import[
3
3
  "shell.kubectl_commands",
4
4
  "shell.local_shell",
5
+ "kubernetes.resources_fetcher",
5
6
  "ui"
6
7
  ]
7
8
 
@@ -10,10 +11,8 @@ class KuberKit::Actions::KubectlAttacher
10
11
  kubeconfig_path = KuberKit.current_configuration.kubeconfig_path
11
12
  deployer_namespace = KuberKit.current_configuration.deployer_namespace
12
13
 
13
- if !pod_name
14
- resources = kubectl_commands.get_resources(local_shell, "deployments", jsonpath: ".items[*].metadata.name")
15
- options = resources.split(" ").map{|d| "deploy/#{d}" }
16
- pod_name = ui.prompt("Please select deployment to attach", options)
14
+ if !pod_name
15
+ pod_name = resources_fetcher.call("attach")
17
16
  end
18
17
 
19
18
  kubectl_commands.exec(
@@ -2,6 +2,7 @@ class KuberKit::Actions::KubectlConsole
2
2
  include KuberKit::Import[
3
3
  "shell.kubectl_commands",
4
4
  "shell.local_shell",
5
+ "kubernetes.resources_fetcher",
5
6
  "ui"
6
7
  ]
7
8
 
@@ -11,9 +12,7 @@ class KuberKit::Actions::KubectlConsole
11
12
  deployer_namespace = KuberKit.current_configuration.deployer_namespace
12
13
 
13
14
  if !pod_name
14
- resources = kubectl_commands.get_resources(local_shell, "deployments", jsonpath: ".items[*].metadata.name")
15
- options = resources.split(" ").map{|d| "deploy/#{d}" }
16
- pod_name = ui.prompt("Please select deployment to attach", options)
15
+ pod_name = resources_fetcher.call("attach")
17
16
  end
18
17
 
19
18
  kubectl_commands.exec(
@@ -2,6 +2,7 @@ class KuberKit::Actions::KubectlDescribe
2
2
  include KuberKit::Import[
3
3
  "shell.kubectl_commands",
4
4
  "shell.local_shell",
5
+ "kubernetes.resources_fetcher",
5
6
  "ui"
6
7
  ]
7
8
 
@@ -11,7 +12,7 @@ class KuberKit::Actions::KubectlDescribe
11
12
  deployer_namespace = KuberKit.current_configuration.deployer_namespace
12
13
 
13
14
  if !resource_name
14
- resource_name = get_resource_name
15
+ resource_name = resources_fetcher.call("describe", include_ingresses: true, include_pods: true)
15
16
  end
16
17
 
17
18
  args = nil
@@ -32,25 +33,4 @@ class KuberKit::Actions::KubectlDescribe
32
33
 
33
34
  false
34
35
  end
35
-
36
- def get_resource_name
37
- deployments = kubectl_commands.get_resources(local_shell, "deployments", jsonpath: ".items[*].metadata.name")
38
- options = deployments.split(" ").map{|d| "deploy/#{d}" }
39
- options += ["ingresses", "pods"]
40
- option = ui.prompt("Please select resource to describe", options)
41
-
42
- if option == "ingresses"
43
- ingresses = kubectl_commands.get_resources(local_shell, "ingresses", jsonpath: ".items[*].metadata.name")
44
- options = ingresses.split(" ").map{|d| "ingresses/#{d}" }
45
- return ui.prompt("Please select ingress to describe", options)
46
- end
47
-
48
- if option == "pods"
49
- ingresses = kubectl_commands.get_resources(local_shell, "pods", jsonpath: ".items[*].metadata.name")
50
- options = ingresses.split(" ").map{|d| "pods/#{d}" }
51
- return ui.prompt("Please select pod to describe", options)
52
- end
53
-
54
- option
55
- end
56
36
  end
@@ -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,6 +2,7 @@ class KuberKit::Actions::KubectlLogs
2
2
  include KuberKit::Import[
3
3
  "shell.kubectl_commands",
4
4
  "shell.local_shell",
5
+ "kubernetes.resources_fetcher",
5
6
  "ui"
6
7
  ]
7
8
 
@@ -11,9 +12,7 @@ class KuberKit::Actions::KubectlLogs
11
12
  deployer_namespace = KuberKit.current_configuration.deployer_namespace
12
13
 
13
14
  if !pod_name
14
- deployments = kubectl_commands.get_resources(local_shell, "deployments", jsonpath: ".items[*].metadata.name")
15
- deploy_options = deployments.split(" ").map{|d| "deploy/#{d}" }
16
- pod_name = ui.prompt("Please select deployment to attach", deploy_options)
15
+ pod_name = resources_fetcher.call("attach")
17
16
  end
18
17
 
19
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
+ deployments = resources_fetcher.call("deployments")
19
+
20
+ missing_services = services.select{ |s| !deployments.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
@@ -4,6 +4,7 @@ class KuberKit::Actions::ServiceDeployer
4
4
  "service_deployer.service_list_resolver",
5
5
  "core.service_store",
6
6
  "shell.local_shell",
7
+ "tools.process_cleaner",
7
8
  "ui",
8
9
  service_deployer: "service_deployer.action_handler",
9
10
  ]
@@ -56,6 +57,8 @@ class KuberKit::Actions::ServiceDeployer
56
57
  ui.print_error("Error", e.message)
57
58
 
58
59
  false
60
+ rescue Interrupt => e
61
+ process_cleaner.clean
59
62
  end
60
63
 
61
64
  def deploy_services(service_names)
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
@@ -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
@@ -261,6 +277,14 @@ class KuberKit::Container
261
277
  KuberKit::ServiceReader::Reader.new
262
278
  end
263
279
 
280
+ register "kubernetes.resource_selector" do
281
+ KuberKit::Kubernetes::ResourceSelector.new
282
+ end
283
+
284
+ register "kubernetes.resources_fetcher" do
285
+ KuberKit::Kubernetes::ResourcesFetcher.new
286
+ end
287
+
264
288
  register "ui" do
265
289
  if KuberKit.ui_mode == :debug
266
290
  KuberKit::UI::Debug.new
@@ -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
@@ -0,0 +1,18 @@
1
+ class KuberKit::Kubernetes::ResourcesFetcher
2
+ include KuberKit::Import[
3
+ "shell.kubectl_commands",
4
+ "shell.local_shell",
5
+ ]
6
+
7
+ Contract String => ArrayOf[String]
8
+ def call(resource_type)
9
+ current_configuration = KuberKit.current_configuration
10
+
11
+ kubectl_commands.get_resources(
12
+ local_shell, resource_type,
13
+ jsonpath: ".items[*].metadata.name",
14
+ kubeconfig_path: current_configuration.kubeconfig_path,
15
+ namespace: current_configuration.deployer_namespace
16
+ )
17
+ end
18
+ 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
- container_name = strategy_options.fetch(:container_name, service.uri)
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,12 +69,19 @@ 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,
64
- command: command_name,
65
- args: custom_args,
66
- detached: !!strategy_options[:detached]
81
+ command: command_name,
82
+ args: custom_args,
83
+ detached: !!strategy_options[:detached],
84
+ interactive: !strategy_options[:detached]
67
85
  )
68
86
  end
69
87
  end
@@ -29,10 +29,11 @@ class KuberKit::ServiceDeployer::Strategies::DockerCompose < KuberKit::ServiceDe
29
29
  custom_args = strategy_options.fetch(:custom_args, nil)
30
30
 
31
31
  docker_compose_commands.run(shell, config_path,
32
- service: service_name,
33
- command: command_name,
34
- args: custom_args,
35
- detached: !!strategy_options[:detached]
32
+ service: service_name,
33
+ command: command_name,
34
+ args: custom_args,
35
+ detached: !!strategy_options[:detached],
36
+ interactive: !strategy_options[:detached]
36
37
  )
37
38
  end
38
39
  end
@@ -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") if result.is_a?(String)
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 && result != ""
75
+ result.any?
76
76
  end
77
77
 
78
78
  def delete_resource(shell, resource_type, resource_name, kubeconfig_path: nil, namespace: nil)
@@ -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
@@ -1,3 +1,3 @@
1
1
  module KuberKit
2
- VERSION = "0.4.5"
2
+ VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kuber_kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Iskander Khaziev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-09 00:00:00.000000000 Z
11
+ date: 2021-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: contracts-lite
@@ -209,7 +209,9 @@ files:
209
209
  - lib/kuber_kit/actions/kubectl_attacher.rb
210
210
  - lib/kuber_kit/actions/kubectl_console.rb
211
211
  - lib/kuber_kit/actions/kubectl_describe.rb
212
+ - lib/kuber_kit/actions/kubectl_env.rb
212
213
  - lib/kuber_kit/actions/kubectl_logs.rb
214
+ - lib/kuber_kit/actions/service_checker.rb
213
215
  - lib/kuber_kit/actions/service_deployer.rb
214
216
  - lib/kuber_kit/actions/service_reader.rb
215
217
  - lib/kuber_kit/actions/template_reader.rb
@@ -273,6 +275,8 @@ files:
273
275
  - lib/kuber_kit/image_compiler/image_builder.rb
274
276
  - lib/kuber_kit/image_compiler/image_dependency_resolver.rb
275
277
  - lib/kuber_kit/image_compiler/version_tag_builder.rb
278
+ - lib/kuber_kit/kubernetes/resource_selector.rb
279
+ - lib/kuber_kit/kubernetes/resources_fetcher.rb
276
280
  - lib/kuber_kit/preprocessing/file_preprocessor.rb
277
281
  - lib/kuber_kit/preprocessing/text_preprocessor.rb
278
282
  - lib/kuber_kit/service_deployer/action_handler.rb
@@ -293,6 +297,7 @@ files:
293
297
  - lib/kuber_kit/shell/commands/git_commands.rb
294
298
  - lib/kuber_kit/shell/commands/kubectl_commands.rb
295
299
  - lib/kuber_kit/shell/commands/rsync_commands.rb
300
+ - lib/kuber_kit/shell/commands/system_commands.rb
296
301
  - lib/kuber_kit/shell/local_shell.rb
297
302
  - lib/kuber_kit/shell/ssh_session.rb
298
303
  - lib/kuber_kit/shell/ssh_shell.rb
@@ -302,6 +307,7 @@ files:
302
307
  - lib/kuber_kit/template_reader/strategies/artifact_file.rb
303
308
  - lib/kuber_kit/tools/file_presence_checker.rb
304
309
  - lib/kuber_kit/tools/logger_factory.rb
310
+ - lib/kuber_kit/tools/process_cleaner.rb
305
311
  - lib/kuber_kit/ui.rb
306
312
  - lib/kuber_kit/ui/api.rb
307
313
  - lib/kuber_kit/ui/debug.rb