kuber_kit 0.4.4 → 0.4.9

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: c5c1697ed582055ca1d233797dcc663ffd8c2e7a00763b7d8a9ea8ca639b2270
4
- data.tar.gz: a707b96dc99201d2d3c2338ceaef7d53d5241772f718b2453cb6249ce82b2335
3
+ metadata.gz: 766eae8b402b82c6e307942d24f2ee60d87197ef0b966f8551e17b2926a8210b
4
+ data.tar.gz: eae14447e34ab527affdfbbbdd9b34027470b6c2b54b63bb27be8cdf651bbd27
5
5
  SHA512:
6
- metadata.gz: be389af37cb52dd30f7a7cd6795231d3e7894fea24d303c1bdcb47f84b74e4e8b558a20e04e611a2263ae2d44cb008edd5e77beba4011d137fb5df06dd63b909
7
- data.tar.gz: ee6144b4aad93cfa417d3cad69bfb1cc14b11fea014a50d02bfa2996306fa4b32de7923b9d8105ca79d7793ffac5dc123bb5bb7f2d4562e97405dafab3399956
6
+ metadata.gz: '086f8e0c1983f00c3b517d4bf8a90c53d4ba58395b429d65a0dd2afeb8e80aae0e5120adf3ea1936b3f7c343de57378ef4e6e5b45c4836eb3de82f73a8198bc7'
7
+ data.tar.gz: d236328533a9f15eba54dba8c777e54821ddab141aaf46ada97e88d35a7fc7fe7048bcb49ddb719b081d55a36883a8434c39632343a210b174343851eb43fa93
data/Gemfile.lock CHANGED
@@ -1,19 +1,20 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kuber_kit (0.4.4)
4
+ kuber_kit (0.4.9)
5
5
  cli-ui
6
6
  contracts-lite
7
7
  dry-auto_inject
8
8
  net-ssh
9
9
  thor
10
+ tty-prompt
10
11
 
11
12
  GEM
12
13
  remote: https://rubygems.org/
13
14
  specs:
14
15
  cli-ui (1.4.0)
15
16
  coderay (1.1.3)
16
- concurrent-ruby (1.1.7)
17
+ concurrent-ruby (1.1.8)
17
18
  contracts-lite (0.15.0)
18
19
  diff-lcs (1.4.4)
19
20
  docile (1.3.2)
@@ -29,6 +30,8 @@ GEM
29
30
  concurrent-ruby (~> 1.0)
30
31
  method_source (1.0.0)
31
32
  net-ssh (6.1.0)
33
+ pastel (0.8.0)
34
+ tty-color (~> 0.5)
32
35
  pry (0.13.1)
33
36
  coderay (~> 1.1)
34
37
  method_source (~> 1.0)
@@ -52,7 +55,18 @@ GEM
52
55
  simplecov_json_formatter (~> 0.1)
53
56
  simplecov-html (0.12.3)
54
57
  simplecov_json_formatter (0.1.2)
55
- thor (1.0.1)
58
+ thor (1.1.0)
59
+ tty-color (0.6.0)
60
+ tty-cursor (0.7.1)
61
+ tty-prompt (0.23.0)
62
+ pastel (~> 0.8)
63
+ tty-reader (~> 0.8)
64
+ tty-reader (0.9.0)
65
+ tty-cursor (~> 0.7)
66
+ tty-screen (~> 0.8)
67
+ wisper (~> 2.0)
68
+ tty-screen (0.8.1)
69
+ wisper (2.0.1)
56
70
 
57
71
  PLATFORMS
58
72
  ruby
data/TODO.md CHANGED
@@ -1,8 +1,8 @@
1
- - https://ttytoolkit.org/
2
- - do not show result for images list, if list is too large
1
+ - do not show result for images list, if list is too large (Mikhail)
2
+ - add kit get method for interactive kubernetes
3
3
  - kit status should show the list of services and their status, with ability to select & view logs
4
- - allow deploying only services enabled for specific configuration
5
4
  - find a way to always deploy some service, e.g. for migrations and env_files
6
5
  - template should be able to set default attributes
7
6
  - template should be able to depend on image?
8
- - 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"]
@@ -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/kuber_kit.gemspec CHANGED
@@ -28,6 +28,7 @@ Gem::Specification.new do |spec|
28
28
  spec.add_dependency "thor"
29
29
  spec.add_dependency "cli-ui"
30
30
  spec.add_dependency "net-ssh"
31
+ spec.add_dependency "tty-prompt"
31
32
 
32
33
  spec.add_development_dependency "bundler", "~> 1.17"
33
34
  spec.add_development_dependency "rake", "~> 10.0"
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
 
@@ -167,6 +169,7 @@ module KuberKit
167
169
  autoload :KubectlApplier, 'actions/kubectl_applier'
168
170
  autoload :KubectlAttacher, 'actions/kubectl_attacher'
169
171
  autoload :KubectlConsole, 'actions/kubectl_console'
172
+ autoload :KubectlDescribe, 'actions/kubectl_describe'
170
173
  autoload :KubectlLogs, 'actions/kubectl_logs'
171
174
  end
172
175
 
@@ -174,6 +177,10 @@ module KuberKit
174
177
  autoload :Inspectable, 'extensions/inspectable'
175
178
  end
176
179
 
180
+ module Kubernetes
181
+ autoload :ResourcesFetcher, 'kubernetes/resources_fetcher'
182
+ end
183
+
177
184
  module UI
178
185
  autoload :Interactive, 'ui/interactive'
179
186
  autoload :Simple, 'ui/simple'
@@ -18,6 +18,7 @@ class KuberKit::Actions::ConfigurationLoader
18
18
  infra_path = options[:infra_path] || File.join(root_path, configs.infra_dirname)
19
19
  configurations_path = options[:configurations_path] || File.join(root_path, configs.configurations_dirname)
20
20
  configuration_name = options[:configuration] || ENV["KUBER_KIT_CONFIGURATION"]
21
+ load_inventory = options.fetch(:load_inventory, true)
21
22
 
22
23
  ui.print_debug "ConfigurationLoader", "Launching kuber_kit with:"
23
24
  ui.print_debug "ConfigurationLoader", " Root path: #{root_path.to_s.yellow}"
@@ -40,25 +41,27 @@ class KuberKit::Actions::ConfigurationLoader
40
41
  load_configurations(configurations_path, configuration_name)
41
42
  load_infrastructure(infra_path)
42
43
 
43
- ui.create_task("Updating artifacts") do |task|
44
- artifacts = KuberKit.current_configuration.artifacts.values
45
- artifacts_updater.update(local_shell, artifacts)
46
- task.update_title("Updated #{artifacts.count} artifacts")
47
- end
44
+ if load_inventory
45
+ ui.create_task("Updating artifacts") do |task|
46
+ artifacts = KuberKit.current_configuration.artifacts.values
47
+ artifacts_updater.update(local_shell, artifacts)
48
+ task.update_title("Updated #{artifacts.count} artifacts")
49
+ end
48
50
 
49
- ui.create_task("Loading image definitions") do |task|
50
- files = image_store.load_definitions(images_path)
51
+ ui.create_task("Loading image definitions") do |task|
52
+ files = image_store.load_definitions(images_path)
51
53
 
52
- configs.additional_images_paths.each do |path|
53
- files += image_store.load_definitions(path)
54
- end
54
+ configs.additional_images_paths.each do |path|
55
+ files += image_store.load_definitions(path)
56
+ end
55
57
 
56
- task.update_title("Loaded #{files.count} image definitions")
57
- end
58
+ task.update_title("Loaded #{files.count} image definitions")
59
+ end
58
60
 
59
- ui.create_task("Loading service definitions") do |task|
60
- files = service_store.load_definitions(services_path)
61
- task.update_title("Loaded #{files.count} service definitions")
61
+ ui.create_task("Loading service definitions") do |task|
62
+ files = service_store.load_definitions(services_path)
63
+ task.update_title("Loaded #{files.count} service definitions")
64
+ end
62
65
  end
63
66
 
64
67
  true
@@ -84,9 +87,7 @@ class KuberKit::Actions::ConfigurationLoader
84
87
 
85
88
  if configuration_store.count > 1 && configuration_name.nil?
86
89
  options = all_configurations.map(&:configuration_name).map(&:to_s)
87
- ui.prompt("Please select configuration name (or set it using -C option)", options) do |selection|
88
- configuration_name = selection
89
- end
90
+ configuration_name = ui.prompt("Please select configuration name (or set it using -C option)", options)
90
91
  end
91
92
 
92
93
  KuberKit.set_configuration_name(configuration_name)
@@ -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(
@@ -0,0 +1,36 @@
1
+ class KuberKit::Actions::KubectlDescribe
2
+ include KuberKit::Import[
3
+ "shell.kubectl_commands",
4
+ "shell.local_shell",
5
+ "kubernetes.resources_fetcher",
6
+ "ui"
7
+ ]
8
+
9
+ Contract Maybe[String], Hash => Any
10
+ def call(resource_name, options)
11
+ kubeconfig_path = KuberKit.current_configuration.kubeconfig_path
12
+ deployer_namespace = KuberKit.current_configuration.deployer_namespace
13
+
14
+ if !resource_name
15
+ resource_name = resources_fetcher.call("describe", include_ingresses: true, include_pods: true)
16
+ end
17
+
18
+ args = nil
19
+ if options[:follow]
20
+ args = "-f"
21
+ end
22
+
23
+ kubectl_commands.describe(
24
+ local_shell, resource_name,
25
+ args: args,
26
+ kubeconfig_path: kubeconfig_path,
27
+ namespace: deployer_namespace
28
+ )
29
+
30
+ true
31
+ rescue KuberKit::Error => e
32
+ ui.print_error("Error", e.message)
33
+
34
+ false
35
+ end
36
+ 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
@@ -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
  ]
@@ -20,8 +21,9 @@ class KuberKit::Actions::ServiceDeployer
20
21
  end
21
22
 
22
23
  service_names = service_list_resolver.resolve(
23
- services: services || [],
24
- tags: tags || []
24
+ services: services || [],
25
+ tags: tags || [],
26
+ enabled_services: KuberKit.current_configuration.enabled_services.map(&:to_s)
25
27
  )
26
28
 
27
29
  unless service_names.any?
@@ -34,7 +36,7 @@ class KuberKit::Actions::ServiceDeployer
34
36
 
35
37
  if require_confirmation
36
38
  result = ui.prompt("Please confirm to continue deployment", ["confirm".green, "cancel".red])
37
- return false unless result == "confirm".green
39
+ return false unless ["confirm".green, "confirm", "yes"].include?(result)
38
40
  end
39
41
 
40
42
  services = service_names.map do |service_name|
@@ -43,7 +45,11 @@ class KuberKit::Actions::ServiceDeployer
43
45
 
44
46
  images_names = services.map(&:images).flatten.uniq
45
47
 
46
- compile_images(images_names) unless skip_compile
48
+ unless skip_compile
49
+ compile_result = compile_images(images_names)
50
+ return false unless compile_result
51
+ end
52
+
47
53
  deployment_result = deploy_services(service_names)
48
54
 
49
55
  { services: service_names, deployment: deployment_result }
@@ -51,6 +57,8 @@ class KuberKit::Actions::ServiceDeployer
51
57
  ui.print_error("Error", e.message)
52
58
 
53
59
  false
60
+ rescue Interrupt => e
61
+ process_cleaner.clean
54
62
  end
55
63
 
56
64
  def deploy_services(service_names)
@@ -75,7 +83,8 @@ class KuberKit::Actions::ServiceDeployer
75
83
  end
76
84
 
77
85
  def compile_images(images_names)
78
- image_compiler.call(images_names, {}) if images_names.any?
86
+ return true if images_names.empty?
87
+ image_compiler.call(images_names, {})
79
88
  end
80
89
 
81
90
  def show_tags_selection()
@@ -92,12 +101,12 @@ class KuberKit::Actions::ServiceDeployer
92
101
  .sort
93
102
  .map(&:to_s)
94
103
 
95
- ui.prompt("Please select which tag to deploy", tags) do |selected_tag|
96
- if selected_tag == specific_service_option
97
- show_service_selection
98
- else
99
- return [[], [selected_tag]]
100
- end
104
+ selected_tag = ui.prompt("Please select which tag to deploy", tags)
105
+
106
+ if selected_tag == specific_service_option
107
+ show_service_selection
108
+ else
109
+ [[], [selected_tag]]
101
110
  end
102
111
  end
103
112
 
@@ -110,8 +119,11 @@ class KuberKit::Actions::ServiceDeployer
110
119
  .sort
111
120
  .map(&:to_s)
112
121
 
113
- ui.prompt("Please select which service to deploy", services) do |selected_service|
114
- return [[selected_service], []]
122
+ if services.empty?
123
+ return [[], []]
115
124
  end
125
+
126
+ selected_service = ui.prompt("Please select which service to deploy", services)
127
+ [[selected_service], []]
116
128
  end
117
129
  end
data/lib/kuber_kit/cli.rb CHANGED
@@ -30,7 +30,7 @@ class KuberKit::CLI < Thor
30
30
  end
31
31
  end
32
32
 
33
- desc "deploy CONTEXT_NAME", "Deploy CONTEXT_NAME with kubectl"
33
+ desc "deploy -t CONTEXT_NAME", "Deploy CONTEXT_NAME with kubectl"
34
34
  method_option :services, :type => :array, aliases: ["-s"], repeatable: true
35
35
  method_option :tags, :type => :array, aliases: ["-t"], repeatable: true
36
36
  method_option :skip_compile, :type => :boolean, aliases: ["-B"]
@@ -108,7 +108,7 @@ class KuberKit::CLI < Thor
108
108
  def console(pod_name = nil)
109
109
  setup(options)
110
110
 
111
- if KuberKit::Container['actions.configuration_loader'].call(options)
111
+ if KuberKit::Container['actions.configuration_loader'].call(options.merge(load_inventory: false))
112
112
  KuberKit::Container['actions.kubectl_console'].call(pod_name, options)
113
113
  end
114
114
  end
@@ -118,11 +118,20 @@ class KuberKit::CLI < Thor
118
118
  def logs(pod_name = nil)
119
119
  setup(options)
120
120
 
121
- if KuberKit::Container['actions.configuration_loader'].call(options)
121
+ if KuberKit::Container['actions.configuration_loader'].call(options.merge(load_inventory: false))
122
122
  KuberKit::Container['actions.kubectl_logs'].call(pod_name, options)
123
123
  end
124
124
  end
125
125
 
126
+ desc "describe RESOURCE_NAME", "Show description for RESOURCE_NAME using kubectl"
127
+ def describe(pod_name = nil)
128
+ setup(options)
129
+
130
+ if KuberKit::Container['actions.configuration_loader'].call(options.merge(load_inventory: false))
131
+ KuberKit::Container['actions.kubectl_describe'].call(pod_name, options)
132
+ end
133
+ end
134
+
126
135
  desc "version", "Print current version"
127
136
  def version
128
137
  puts KuberKit::VERSION
@@ -151,4 +160,21 @@ class KuberKit::CLI < Thor
151
160
  def print_result(message, data = {})
152
161
  KuberKit::Container['ui'].print_result(message, data)
153
162
  end
163
+
164
+ def cleanup_processes
165
+ # Stop all threads
166
+ Thread.list.each do |t|
167
+ t.abort_on_exception = false
168
+ t.report_on_exception = false
169
+ Thread.kill(t) if t != Thread.current
170
+ end
171
+
172
+ # Find all system calls
173
+ child_pids_raw = `ps auxww | grep '[K]IT=#{Process.pid}' | awk '{print $2}'`
174
+ child_pids = child_pids_raw.to_s.split("\n").reject(&:empty?)
175
+ child_pids.each do |pid|
176
+ puts "Killing child process: #{pid}"
177
+ Process.kill("SIGHUP", pid.to_i)
178
+ end
179
+ end
154
180
  end
@@ -37,6 +37,10 @@ class KuberKit::Container
37
37
  KuberKit::Actions::KubectlConsole.new
38
38
  end
39
39
 
40
+ register "actions.kubectl_describe" do
41
+ KuberKit::Actions::KubectlDescribe.new
42
+ end
43
+
40
44
  register "actions.kubectl_logs" do
41
45
  KuberKit::Actions::KubectlLogs.new
42
46
  end
@@ -117,6 +121,10 @@ class KuberKit::Container
117
121
  KuberKit::Container["tools.logger_factory"].create()
118
122
  end
119
123
 
124
+ register "tools.process_cleaner" do
125
+ KuberKit::Tools::ProcessCleaner.new
126
+ end
127
+
120
128
  register "shell.bash_commands" do
121
129
  KuberKit::Shell::Commands::BashCommands.new
122
130
  end
@@ -141,6 +149,10 @@ class KuberKit::Container
141
149
  KuberKit::Shell::Commands::KubectlCommands.new
142
150
  end
143
151
 
152
+ register "shell.system_commands" do
153
+ KuberKit::Shell::Commands::SystemCommands.new
154
+ end
155
+
144
156
  register "shell.local_shell" do
145
157
  KuberKit::Shell::LocalShell.new
146
158
  end
@@ -257,6 +269,10 @@ class KuberKit::Container
257
269
  KuberKit::ServiceReader::Reader.new
258
270
  end
259
271
 
272
+ register "kubernetes.resources_fetcher" do
273
+ KuberKit::Kubernetes::ResourcesFetcher.new
274
+ end
275
+
260
276
  register "ui" do
261
277
  if KuberKit.ui_mode == :debug
262
278
  KuberKit::UI::Debug.new
@@ -1,6 +1,6 @@
1
1
  class KuberKit::Core::Configuration
2
2
  attr_reader :name, :artifacts, :registries, :env_files, :templates, :kubeconfig_path,
3
- :services_attributes, :build_servers, :global_build_vars,
3
+ :services_attributes, :enabled_services, :build_servers, :global_build_vars,
4
4
  :deployer_strategy, :deployer_namespace, :deployer_require_confirimation
5
5
 
6
6
  Contract KeywordArgs[
@@ -11,6 +11,7 @@ class KuberKit::Core::Configuration
11
11
  templates: Hash,
12
12
  kubeconfig_path: Maybe[String],
13
13
  services_attributes: HashOf[Symbol => Hash],
14
+ enabled_services: ArrayOf[Symbol],
14
15
  build_servers: ArrayOf[KuberKit::Core::BuildServers::AbstractBuildServer],
15
16
  global_build_vars: HashOf[Symbol => Any],
16
17
  deployer_strategy: Symbol,
@@ -18,7 +19,7 @@ class KuberKit::Core::Configuration
18
19
  deployer_require_confirimation: Bool,
19
20
  ] => Any
20
21
  def initialize(name:, artifacts:, registries:, env_files:, templates:, kubeconfig_path:,
21
- services_attributes:, build_servers:, global_build_vars:,
22
+ services_attributes:, enabled_services:, build_servers:, global_build_vars:,
22
23
  deployer_strategy:, deployer_namespace:, deployer_require_confirimation:)
23
24
  @name = name
24
25
  @artifacts = artifacts
@@ -28,6 +29,7 @@ class KuberKit::Core::Configuration
28
29
  @kubeconfig_path = kubeconfig_path
29
30
  @build_servers = build_servers
30
31
  @services_attributes = services_attributes
32
+ @enabled_services = enabled_services
31
33
  @global_build_vars = global_build_vars
32
34
  @deployer_strategy = deployer_strategy
33
35
  @deployer_namespace = deployer_namespace
@@ -28,6 +28,7 @@ class KuberKit::Core::ConfigurationFactory
28
28
  kubeconfig_path: configuration_attrs.kubeconfig_path,
29
29
  build_servers: build_servers,
30
30
  services_attributes: configuration_attrs.services_attributes,
31
+ enabled_services: configuration_attrs.enabled_services,
31
32
  global_build_vars: configuration_attrs.global_build_vars || {},
32
33
  deployer_strategy: configuration_attrs.deployer_strategy || configs.deployer_strategy,
33
34
  deployer_namespace: configuration_attrs.deployer_namespace,
@@ -0,0 +1,41 @@
1
+ class KuberKit::Kubernetes::ResourcesFetcher
2
+ include KuberKit::Import[
3
+ "shell.kubectl_commands",
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 = 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
30
+
31
+ option
32
+ end
33
+
34
+ def get_resources(type)
35
+ kubectl_commands.get_resources(
36
+ local_shell, type,
37
+ jsonpath: ".items[*].metadata.name",
38
+ namespace: KuberKit.current_configuration.deployer_namespace
39
+ )
40
+ end
41
+ end
@@ -4,10 +4,11 @@ class KuberKit::ServiceDeployer::ServiceListResolver
4
4
  ]
5
5
 
6
6
  Contract KeywordArgs[
7
- services: Optional[ArrayOf[String]],
8
- tags: Optional[ArrayOf[String]]
7
+ services: Optional[ArrayOf[String]],
8
+ tags: Optional[ArrayOf[String]],
9
+ enabled_services: Optional[ArrayOf[String]]
9
10
  ] => ArrayOf[String]
10
- def resolve(services: [], tags: [])
11
+ def resolve(services: [], tags: [], enabled_services: [])
11
12
  all_definitions = service_store.all_definitions.values
12
13
 
13
14
  included_services, excluded_services = split_by_inclusion(services)
@@ -29,7 +30,13 @@ class KuberKit::ServiceDeployer::ServiceListResolver
29
30
  matches_any?(service_tags, excluded_tags)
30
31
  end
31
32
 
32
- included_definitions.map(&:service_name).map(&:to_s)
33
+ included_services = included_definitions.map(&:service_name).map(&:to_s)
34
+
35
+ if enabled_services.any?
36
+ included_services = included_services.select{ |s| enabled_services.include?(s) }
37
+ end
38
+
39
+ included_services
33
40
  end
34
41
 
35
42
  Contract Array => Array
@@ -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
@@ -14,7 +14,7 @@ class KuberKit::Shell::Commands::KubectlCommands
14
14
  command_parts << "-n #{namespace}"
15
15
  end
16
16
 
17
- command_parts += Array(command_list)
17
+ command_parts += Array(command_list).compact
18
18
 
19
19
  if interactive
20
20
  shell.interactive!(command_parts.join(" "))
@@ -41,15 +41,11 @@ class KuberKit::Shell::Commands::KubectlCommands
41
41
  end
42
42
 
43
43
  def logs(shell, pod_name, args: nil, kubeconfig_path: nil, namespace: nil)
44
- command_parts = []
45
- command_parts << "logs"
46
-
47
- if args
48
- command_parts << args
49
- end
44
+ kubectl_run(shell, ["logs", args, pod_name], kubeconfig_path: kubeconfig_path, interactive: true, namespace: namespace)
45
+ end
50
46
 
51
- command_parts << pod_name
52
- kubectl_run(shell, command_parts, kubeconfig_path: kubeconfig_path, interactive: true, namespace: namespace)
47
+ def describe(shell, resource_name, args: nil, kubeconfig_path: nil, namespace: nil)
48
+ kubectl_run(shell, ["describe", args, resource_name], kubeconfig_path: kubeconfig_path, interactive: true, namespace: namespace)
53
49
  end
54
50
 
55
51
  def get_resources(shell, resource_type, field_selector: nil, jsonpath: ".items[*].metadata.name", kubeconfig_path: nil, namespace: nil)
@@ -64,7 +60,12 @@ class KuberKit::Shell::Commands::KubectlCommands
64
60
  command_parts << "-o jsonpath='{#{jsonpath}}'"
65
61
  end
66
62
 
67
- kubectl_run(shell, command_parts, kubeconfig_path: kubeconfig_path, namespace: namespace)
63
+ result = kubectl_run(shell, command_parts, kubeconfig_path: kubeconfig_path, namespace: namespace)
64
+
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)
67
+
68
+ result
68
69
  end
69
70
 
70
71
  def resource_exists?(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,4 +1,5 @@
1
1
  require 'cli/ui'
2
+ require "tty-prompt"
2
3
 
3
4
  class KuberKit::UI::Interactive
4
5
  include KuberKit::Import[
@@ -42,17 +43,10 @@ class KuberKit::UI::Interactive
42
43
  end
43
44
 
44
45
  def prompt(text, options, &callback)
45
- CLI::UI::Prompt.ask(text) do |handler|
46
- options.each do |option|
47
- if callback
48
- handler.option(option, &callback)
49
- else
50
- handler.option(option) do |selection|
51
- selection
52
- end
53
- end
54
- end
55
- end
46
+ prompt = TTY::Prompt.new
47
+ prompt.select(text, options, filter: true, per_page: 10)
48
+ rescue TTY::Reader::InputInterrupt
49
+ raise KuberKit::Error.new("Selection cancelled.")
56
50
  end
57
51
 
58
52
  private
@@ -97,10 +97,9 @@ class KuberKit::UI::Simple
97
97
  print_debug("Result", "---------------------------")
98
98
  end
99
99
 
100
- def prompt(text, options, &callback)
101
- print_info("Select", text)
100
+ def prompt(text, options)
101
+ print_info("Select", text + "(#{options.join(', ')})")
102
102
  result = $stdin.gets.chomp
103
- callback.call(result) if callback
104
103
  result
105
104
  end
106
105
 
@@ -1,3 +1,3 @@
1
1
  module KuberKit
2
- VERSION = "0.4.4"
2
+ VERSION = "0.4.9"
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.4
4
+ version: 0.4.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Iskander Khaziev
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-26 00:00:00.000000000 Z
11
+ date: 2021-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: contracts-lite
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: tty-prompt
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: bundler
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -194,6 +208,7 @@ files:
194
208
  - lib/kuber_kit/actions/kubectl_applier.rb
195
209
  - lib/kuber_kit/actions/kubectl_attacher.rb
196
210
  - lib/kuber_kit/actions/kubectl_console.rb
211
+ - lib/kuber_kit/actions/kubectl_describe.rb
197
212
  - lib/kuber_kit/actions/kubectl_logs.rb
198
213
  - lib/kuber_kit/actions/service_deployer.rb
199
214
  - lib/kuber_kit/actions/service_reader.rb
@@ -258,6 +273,7 @@ files:
258
273
  - lib/kuber_kit/image_compiler/image_builder.rb
259
274
  - lib/kuber_kit/image_compiler/image_dependency_resolver.rb
260
275
  - lib/kuber_kit/image_compiler/version_tag_builder.rb
276
+ - lib/kuber_kit/kubernetes/resources_fetcher.rb
261
277
  - lib/kuber_kit/preprocessing/file_preprocessor.rb
262
278
  - lib/kuber_kit/preprocessing/text_preprocessor.rb
263
279
  - lib/kuber_kit/service_deployer/action_handler.rb
@@ -278,6 +294,7 @@ files:
278
294
  - lib/kuber_kit/shell/commands/git_commands.rb
279
295
  - lib/kuber_kit/shell/commands/kubectl_commands.rb
280
296
  - lib/kuber_kit/shell/commands/rsync_commands.rb
297
+ - lib/kuber_kit/shell/commands/system_commands.rb
281
298
  - lib/kuber_kit/shell/local_shell.rb
282
299
  - lib/kuber_kit/shell/ssh_session.rb
283
300
  - lib/kuber_kit/shell/ssh_shell.rb
@@ -287,6 +304,7 @@ files:
287
304
  - lib/kuber_kit/template_reader/strategies/artifact_file.rb
288
305
  - lib/kuber_kit/tools/file_presence_checker.rb
289
306
  - lib/kuber_kit/tools/logger_factory.rb
307
+ - lib/kuber_kit/tools/process_cleaner.rb
290
308
  - lib/kuber_kit/ui.rb
291
309
  - lib/kuber_kit/ui/api.rb
292
310
  - lib/kuber_kit/ui/debug.rb
@@ -297,7 +315,7 @@ homepage: https://github.com/ArtStation/kuber_kit
297
315
  licenses:
298
316
  - MIT
299
317
  metadata: {}
300
- post_install_message:
318
+ post_install_message:
301
319
  rdoc_options: []
302
320
  require_paths:
303
321
  - lib
@@ -312,8 +330,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
312
330
  - !ruby/object:Gem::Version
313
331
  version: '0'
314
332
  requirements: []
315
- rubygems_version: 3.0.9
316
- signing_key:
333
+ rubygems_version: 3.0.8
334
+ signing_key:
317
335
  specification_version: 4
318
336
  summary: Docker Containers Build & Deployment
319
337
  test_files: []