kuber_kit 0.4.1 → 0.4.6

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: f98d973c015745f6a4ccf054e3b97edbd8302683f747842ad6c9c5b3e4e49087
4
- data.tar.gz: f2e8eb96e320bc73c1c3b03c611d1990515bd55182a93f30b28966b63da0c591
3
+ metadata.gz: 2bcee9236bf3bc1938a2fa671e3d4a060ddf72a113a932365e5804bfc8c15b38
4
+ data.tar.gz: d452258ab40ad77ac5663c872be237032a80d138164b9e60d98d713fe8d5793f
5
5
  SHA512:
6
- metadata.gz: d550a0a8738447c939b5f6085ef71c7b79898854ede9c6e526e07f73fd4cf6a660b5a18c4e9277f80b081dc41f21f3371aafa69099d6383c884e954b7d15d9ae
7
- data.tar.gz: 8b8ae8685c357608a6db776443171a1ea34d387272fe72f4802164e3345c7b6bf37d558d7967e5315d8718dbcf2a6a902cad2c1e3e84bb4de0b5811b1d075574
6
+ metadata.gz: e34e7f2d8106d941e911ce600c692bcc1332f7d16673151641900462cbab1238be707ebff787dbc40ea9f270b0a27543136439353b32b82e4a4d00ceb2f07ce2
7
+ data.tar.gz: 464be38573b8d6bc6fffc83292c0b80e37bfdb725ad367d8243243aed676d98464a43ec69f7a7283007783e0506863da5e78e80753953da9bff7b8f6dfec193c
data/Gemfile.lock CHANGED
@@ -1,19 +1,20 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kuber_kit (0.4.1)
4
+ kuber_kit (0.4.6)
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,6 @@
1
- - https://ttytoolkit.org/
1
+ - add kit get method for interactive kubernetes
2
+ - do not show result for images list, if list is too large
2
3
  - kit status should show the list of services and their status, with ability to select & view logs
3
- - list services and require confirmation before deployment
4
- - add kit logs support, should work similar to kit attach
5
- - allow deploying only services enabled for specific configuration
6
4
  - find a way to always deploy some service, e.g. for migrations and env_files
7
5
  - template should be able to set default attributes
8
6
  - template should be able to depend on image?
@@ -2,4 +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
6
  #.use_build_server(:remote_bs)
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
@@ -167,6 +167,7 @@ module KuberKit
167
167
  autoload :KubectlApplier, 'actions/kubectl_applier'
168
168
  autoload :KubectlAttacher, 'actions/kubectl_attacher'
169
169
  autoload :KubectlConsole, 'actions/kubectl_console'
170
+ autoload :KubectlDescribe, 'actions/kubectl_describe'
170
171
  autoload :KubectlLogs, 'actions/kubectl_logs'
171
172
  end
172
173
 
@@ -174,6 +175,10 @@ module KuberKit
174
175
  autoload :Inspectable, 'extensions/inspectable'
175
176
  end
176
177
 
178
+ module Kubernetes
179
+ autoload :ResourcesFetcher, 'kubernetes/resources_fetcher'
180
+ end
181
+
177
182
  module UI
178
183
  autoload :Interactive, 'ui/interactive'
179
184
  autoload :Simple, 'ui/simple'
@@ -254,6 +259,14 @@ module KuberKit
254
259
  KuberKit::Core::ContextHelper::BaseHelper.class_exec(&proc)
255
260
  end
256
261
 
262
+ def user
263
+ @user ||= ENV["KUBER_KIT_USERNAME"] || `whoami`.chomp
264
+ end
265
+
266
+ def user_id
267
+ @user_id ||= `id -u #{user}`.chomp
268
+ end
269
+
257
270
  def configure(&proc)
258
271
  yield(Container["configs"])
259
272
  end
@@ -17,7 +17,8 @@ class KuberKit::Actions::ConfigurationLoader
17
17
  services_path = options[:services_path] || File.join(root_path, configs.services_dirname)
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
- configuration_name = ENV["KUBER_KIT_CONFIGURATION"] || options[:configuration]
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)
@@ -3,6 +3,7 @@ class KuberKit::Actions::ImageCompiler
3
3
  "image_compiler.image_dependency_resolver",
4
4
  "image_compiler.build_server_pool_factory",
5
5
  "shell.local_shell",
6
+ "configs",
6
7
  "ui",
7
8
  image_compiler: "image_compiler.action_handler",
8
9
  ]
@@ -15,6 +16,7 @@ class KuberKit::Actions::ImageCompiler
15
16
  compiled_images = []
16
17
  compilation_result = {}
17
18
  image_dependency_resolver.each_with_deps(image_names) do |dep_image_names|
19
+ ui.print_debug("ImageCompiler", "Scheduling to compile: #{dep_image_names.inspect}. Limit: #{configs.compile_simultaneous_limit}")
18
20
  result = compile_simultaneously(dep_image_names, build_id, build_server_pool)
19
21
  compiled_images += dep_image_names
20
22
  compilation_result = compilation_result.merge(result)
@@ -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
@@ -9,22 +9,33 @@ class KuberKit::Actions::ServiceDeployer
9
9
  ]
10
10
 
11
11
  Contract KeywordArgs[
12
- services: Maybe[ArrayOf[String]],
13
- tags: Maybe[ArrayOf[String]],
14
- skip_compile: Maybe[Bool],
12
+ services: Maybe[ArrayOf[String]],
13
+ tags: Maybe[ArrayOf[String]],
14
+ skip_compile: Maybe[Bool],
15
+ require_confirmation: Maybe[Bool],
15
16
  ] => Any
16
- def call(services:, tags:, skip_compile: false)
17
+ def call(services:, tags:, skip_compile: false, require_confirmation: false)
17
18
  if services.empty? && tags.empty?
18
19
  services, tags = show_tags_selection
19
20
  end
20
21
 
21
22
  service_names = service_list_resolver.resolve(
22
- services: services || [],
23
- tags: tags || []
23
+ services: services || [],
24
+ tags: tags || [],
25
+ enabled_services: KuberKit.current_configuration.enabled_services.map(&:to_s)
24
26
  )
25
27
 
26
28
  unless service_names.any?
27
29
  ui.print_warning "ServiceDeployer", "No service found with given options, nothing will be deployed."
30
+ return false
31
+ end
32
+
33
+ services_list = service_names.map(&:to_s).map(&:yellow).join(", ")
34
+ ui.print_info "ServiceDeployer", "The following services will be deployed: #{services_list}"
35
+
36
+ if require_confirmation
37
+ result = ui.prompt("Please confirm to continue deployment", ["confirm".green, "cancel".red])
38
+ return false unless ["confirm".green, "confirm", "yes"].include?(result)
28
39
  end
29
40
 
30
41
  services = service_names.map do |service_name|
@@ -33,7 +44,11 @@ class KuberKit::Actions::ServiceDeployer
33
44
 
34
45
  images_names = services.map(&:images).flatten.uniq
35
46
 
36
- compile_images(images_names) unless skip_compile
47
+ unless skip_compile
48
+ compile_result = compile_images(images_names)
49
+ return false unless compile_result
50
+ end
51
+
37
52
  deployment_result = deploy_services(service_names)
38
53
 
39
54
  { services: service_names, deployment: deployment_result }
@@ -65,7 +80,8 @@ class KuberKit::Actions::ServiceDeployer
65
80
  end
66
81
 
67
82
  def compile_images(images_names)
68
- image_compiler.call(images_names, {}) if images_names.any?
83
+ return true if images_names.empty?
84
+ image_compiler.call(images_names, {})
69
85
  end
70
86
 
71
87
  def show_tags_selection()
@@ -82,12 +98,12 @@ class KuberKit::Actions::ServiceDeployer
82
98
  .sort
83
99
  .map(&:to_s)
84
100
 
85
- ui.prompt("Please select which tag to deploy", tags) do |selected_tag|
86
- if selected_tag == specific_service_option
87
- show_service_selection
88
- else
89
- return [[], [selected_tag]]
90
- end
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]]
91
107
  end
92
108
  end
93
109
 
@@ -100,8 +116,11 @@ class KuberKit::Actions::ServiceDeployer
100
116
  .sort
101
117
  .map(&:to_s)
102
118
 
103
- ui.prompt("Please select which service to deploy", services) do |selected_service|
104
- return [[selected_service], []]
119
+ if services.empty?
120
+ return [[], []]
105
121
  end
122
+
123
+ selected_service = ui.prompt("Please select which service to deploy", services)
124
+ [[selected_service], []]
106
125
  end
107
126
  end
data/lib/kuber_kit/cli.rb CHANGED
@@ -15,6 +15,7 @@ class KuberKit::CLI < Thor
15
15
  def compile(image_names_str)
16
16
  setup(options)
17
17
 
18
+ started_at = Time.now.to_i
18
19
  image_names = image_names_str.split(",").map(&:strip).map(&:to_sym)
19
20
 
20
21
  if KuberKit::Container['actions.configuration_loader'].call(options)
@@ -22,29 +23,37 @@ class KuberKit::CLI < Thor
22
23
  end
23
24
 
24
25
  if result
25
- print_result("Image compilation finished!", result: result)
26
+ time = (Time.now.to_i - started_at)
27
+ print_result("Image compilation finished! (#{time}s)", result: result)
26
28
  else
27
29
  exit 1
28
30
  end
29
31
  end
30
32
 
31
- desc "deploy CONTEXT_NAME", "Deploy CONTEXT_NAME with kubectl"
32
- method_option :services, :type => :array, aliases: ["-s"]
33
- method_option :tags, :type => :array, aliases: ["-t"]
34
- method_option :skip_compile, :type => :boolean, aliases: ["-B"]
33
+ desc "deploy -t CONTEXT_NAME", "Deploy CONTEXT_NAME with kubectl"
34
+ method_option :services, :type => :array, aliases: ["-s"], repeatable: true
35
+ method_option :tags, :type => :array, aliases: ["-t"], repeatable: true
36
+ method_option :skip_compile, :type => :boolean, aliases: ["-B"]
37
+ method_option :require_confirmation, :type => :boolean, aliases: ["-r"]
35
38
  def deploy
36
39
  setup(options)
37
40
 
38
41
  if KuberKit::Container['actions.configuration_loader'].call(options)
42
+ require_confirmation = options[:require_confirmation] ||
43
+ KuberKit.current_configuration.deployer_require_confirimation ||
44
+ false
45
+ started_at = Time.now.to_i
39
46
  result = KuberKit::Container['actions.service_deployer'].call(
40
- services: options[:services] || [],
41
- tags: options[:tags] || [],
42
- skip_compile: options[:skip_compile] || false
47
+ services: (options[:services] || []).flatten.uniq,
48
+ tags: (options[:tags] || []).flatten.uniq,
49
+ skip_compile: options[:skip_compile] || false,
50
+ require_confirmation: require_confirmation
43
51
  )
44
52
  end
45
53
 
46
54
  if result
47
- print_result("Service deployment finished!", result: result)
55
+ time = (Time.now.to_i - started_at)
56
+ print_result("Service deployment finished! (#{time}s)", result: result)
48
57
  else
49
58
  exit 1
50
59
  end
@@ -99,7 +108,7 @@ class KuberKit::CLI < Thor
99
108
  def console(pod_name = nil)
100
109
  setup(options)
101
110
 
102
- if KuberKit::Container['actions.configuration_loader'].call(options)
111
+ if KuberKit::Container['actions.configuration_loader'].call(options.merge(load_inventory: false))
103
112
  KuberKit::Container['actions.kubectl_console'].call(pod_name, options)
104
113
  end
105
114
  end
@@ -109,11 +118,20 @@ class KuberKit::CLI < Thor
109
118
  def logs(pod_name = nil)
110
119
  setup(options)
111
120
 
112
- if KuberKit::Container['actions.configuration_loader'].call(options)
121
+ if KuberKit::Container['actions.configuration_loader'].call(options.merge(load_inventory: false))
113
122
  KuberKit::Container['actions.kubectl_logs'].call(pod_name, options)
114
123
  end
115
124
  end
116
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
+
117
135
  desc "version", "Print current version"
118
136
  def version
119
137
  puts KuberKit::VERSION
@@ -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
@@ -257,6 +261,10 @@ class KuberKit::Container
257
261
  KuberKit::ServiceReader::Reader.new
258
262
  end
259
263
 
264
+ register "kubernetes.resources_fetcher" do
265
+ KuberKit::Kubernetes::ResourcesFetcher.new
266
+ end
267
+
260
268
  register "ui" do
261
269
  if KuberKit.ui_mode == :debug
262
270
  KuberKit::UI::Debug.new
@@ -1,35 +1,39 @@
1
1
  class KuberKit::Core::Configuration
2
2
  attr_reader :name, :artifacts, :registries, :env_files, :templates, :kubeconfig_path,
3
- :deployer_strategy, :deployer_namespace, :services_attributes, :build_servers,
4
- :global_build_vars
3
+ :services_attributes, :enabled_services, :build_servers, :global_build_vars,
4
+ :deployer_strategy, :deployer_namespace, :deployer_require_confirimation
5
5
 
6
6
  Contract KeywordArgs[
7
- name: Symbol,
8
- artifacts: Hash,
9
- registries: Hash,
10
- env_files: Hash,
11
- templates: Hash,
12
- kubeconfig_path: Maybe[String],
13
- deployer_strategy: Symbol,
14
- deployer_namespace: Maybe[Symbol],
15
- services_attributes: HashOf[Symbol => Hash],
16
- build_servers: ArrayOf[KuberKit::Core::BuildServers::AbstractBuildServer],
17
- global_build_vars: HashOf[Symbol => Any],
7
+ name: Symbol,
8
+ artifacts: Hash,
9
+ registries: Hash,
10
+ env_files: Hash,
11
+ templates: Hash,
12
+ kubeconfig_path: Maybe[String],
13
+ services_attributes: HashOf[Symbol => Hash],
14
+ enabled_services: ArrayOf[Symbol],
15
+ build_servers: ArrayOf[KuberKit::Core::BuildServers::AbstractBuildServer],
16
+ global_build_vars: HashOf[Symbol => Any],
17
+ deployer_strategy: Symbol,
18
+ deployer_namespace: Maybe[Symbol],
19
+ deployer_require_confirimation: Bool,
18
20
  ] => Any
19
21
  def initialize(name:, artifacts:, registries:, env_files:, templates:, kubeconfig_path:,
20
- deployer_strategy:, deployer_namespace:, services_attributes:, build_servers:,
21
- global_build_vars:)
22
- @name = name
23
- @artifacts = artifacts
24
- @registries = registries
25
- @env_files = env_files
26
- @templates = templates
27
- @kubeconfig_path = kubeconfig_path
28
- @deployer_strategy = deployer_strategy
29
- @deployer_namespace = deployer_namespace
30
- @build_servers = build_servers
22
+ services_attributes:, enabled_services:, build_servers:, global_build_vars:,
23
+ deployer_strategy:, deployer_namespace:, deployer_require_confirimation:)
24
+ @name = name
25
+ @artifacts = artifacts
26
+ @registries = registries
27
+ @env_files = env_files
28
+ @templates = templates
29
+ @kubeconfig_path = kubeconfig_path
30
+ @build_servers = build_servers
31
31
  @services_attributes = services_attributes
32
+ @enabled_services = enabled_services
32
33
  @global_build_vars = global_build_vars
34
+ @deployer_strategy = deployer_strategy
35
+ @deployer_namespace = deployer_namespace
36
+ @deployer_require_confirimation = deployer_require_confirimation
33
37
  end
34
38
 
35
39
  def service_attributes(service_name)
@@ -17,18 +17,19 @@ class KuberKit::Core::ConfigurationDefinition
17
17
 
18
18
  def to_attrs
19
19
  OpenStruct.new(
20
- name: @configuration_name,
21
- artifacts: @artifacts,
22
- registries: @registries,
23
- env_files: @env_files,
24
- templates: @templates,
25
- kubeconfig_path: @kubeconfig_path,
26
- deployer_strategy: @deployer_strategy,
27
- deployer_namespace: @deployer_namespace,
28
- enabled_services: @enabled_services,
29
- build_servers: @build_servers,
20
+ name: @configuration_name,
21
+ artifacts: @artifacts,
22
+ registries: @registries,
23
+ env_files: @env_files,
24
+ templates: @templates,
25
+ kubeconfig_path: @kubeconfig_path,
26
+ enabled_services: @enabled_services,
27
+ build_servers: @build_servers,
30
28
  services_attributes: @services_attributes,
31
29
  global_build_vars: @global_build_vars,
30
+ deployer_strategy: @deployer_strategy,
31
+ deployer_namespace: @deployer_namespace,
32
+ deployer_require_confirimation: @deployer_require_confirimation || false,
32
33
  )
33
34
  end
34
35
 
@@ -94,6 +95,12 @@ class KuberKit::Core::ConfigurationDefinition
94
95
  self
95
96
  end
96
97
 
98
+ def deployer_require_confirimation
99
+ @deployer_require_confirimation = true
100
+
101
+ self
102
+ end
103
+
97
104
  def enabled_services(services)
98
105
  if services.is_a?(Hash)
99
106
  @enabled_services += services.keys.map(&:to_sym)
@@ -20,17 +20,19 @@ class KuberKit::Core::ConfigurationFactory
20
20
  build_servers = fetch_build_servers(configuration_attrs.build_servers)
21
21
 
22
22
  KuberKit::Core::Configuration.new(
23
- name: configuration_attrs.name,
24
- artifacts: artifacts,
25
- registries: registries,
26
- env_files: env_files,
27
- templates: templates,
28
- kubeconfig_path: configuration_attrs.kubeconfig_path,
29
- deployer_strategy: configuration_attrs.deployer_strategy || configs.deployer_strategy,
30
- deployer_namespace: configuration_attrs.deployer_namespace,
31
- build_servers: build_servers,
23
+ name: configuration_attrs.name,
24
+ artifacts: artifacts,
25
+ registries: registries,
26
+ env_files: env_files,
27
+ templates: templates,
28
+ kubeconfig_path: configuration_attrs.kubeconfig_path,
29
+ build_servers: build_servers,
32
30
  services_attributes: configuration_attrs.services_attributes,
31
+ enabled_services: configuration_attrs.enabled_services,
33
32
  global_build_vars: configuration_attrs.global_build_vars || {},
33
+ deployer_strategy: configuration_attrs.deployer_strategy || configs.deployer_strategy,
34
+ deployer_namespace: configuration_attrs.deployer_namespace,
35
+ deployer_require_confirimation: configuration_attrs.deployer_require_confirimation,
34
36
  )
35
37
  end
36
38
 
@@ -20,7 +20,9 @@ class KuberKit::ImageCompiler::ImageDependencyResolver
20
20
  next_dependencies = get_next(image_names, resolved: resolved_dependencies, limit: compile_limit)
21
21
  end
22
22
 
23
- block.call(image_names - resolved_dependencies)
23
+ (image_names - resolved_dependencies).each_slice(compile_limit) do |group|
24
+ block.call(group)
25
+ end
24
26
  end
25
27
 
26
28
  Contract Or[Symbol, ArrayOf[Symbol]], KeywordArgs[
@@ -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
@@ -25,10 +25,11 @@ class KuberKit::ServiceDeployer::Strategies::Docker < KuberKit::ServiceDeployer:
25
25
  end
26
26
 
27
27
  container_name = strategy_options.fetch(:container_name, service.uri)
28
- command_name = strategy_options.fetch(:command_name, "bash")
29
- custom_args = strategy_options.fetch(:custom_args, nil)
28
+ command_name = strategy_options.fetch(:command_name, nil)
29
+ custom_args = strategy_options.fetch(:custom_args, nil)
30
30
  networks = strategy_options.fetch(:networks, [])
31
31
  volumes = strategy_options.fetch(:volumes, [])
32
+ hostname = strategy_options.fetch(:hostname, container_name)
32
33
 
33
34
  image_name = strategy_options.fetch(:image_name, nil)
34
35
  if image_name.nil?
@@ -45,12 +46,16 @@ class KuberKit::ServiceDeployer::Strategies::Docker < KuberKit::ServiceDeployer:
45
46
  if container_name
46
47
  custom_args << "--name #{container_name}"
47
48
  end
49
+ if hostname
50
+ custom_args << "--hostname #{hostname}"
51
+ end
48
52
  networks.each do |network|
49
53
  docker_commands.create_network(shell, network)
50
54
  custom_args << "--network #{network}"
51
55
  end
52
56
  volumes.each do |volume|
53
- docker_commands.create_volume(shell, volume)
57
+ volume_name, _ = volume.split(":")
58
+ docker_commands.create_volume(shell, volume_name) unless volume_name.start_with?("/")
54
59
  custom_args << "--volume #{volume}"
55
60
  end
56
61
 
@@ -25,8 +25,8 @@ class KuberKit::ServiceDeployer::Strategies::DockerCompose < KuberKit::ServiceDe
25
25
  end
26
26
 
27
27
  service_name = strategy_options.fetch(:service_name, service.name.to_s)
28
- command_name = strategy_options.fetch(:command_name, "bash")
29
- custom_args = strategy_options.fetch(:custom_args, nil)
28
+ command_name = strategy_options.fetch(:command_name, nil)
29
+ custom_args = strategy_options.fetch(:custom_args, nil)
30
30
 
31
31
  docker_compose_commands.run(shell, config_path,
32
32
  service: service_name,
@@ -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)
@@ -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.1"
2
+ VERSION = "0.4.6"
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.1
4
+ version: 0.4.6
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-13 00:00:00.000000000 Z
11
+ date: 2021-02-09 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
@@ -297,7 +313,7 @@ homepage: https://github.com/ArtStation/kuber_kit
297
313
  licenses:
298
314
  - MIT
299
315
  metadata: {}
300
- post_install_message:
316
+ post_install_message:
301
317
  rdoc_options: []
302
318
  require_paths:
303
319
  - lib
@@ -312,8 +328,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
312
328
  - !ruby/object:Gem::Version
313
329
  version: '0'
314
330
  requirements: []
315
- rubygems_version: 3.0.9
316
- signing_key:
331
+ rubygems_version: 3.0.8
332
+ signing_key:
317
333
  specification_version: 4
318
334
  summary: Docker Containers Build & Deployment
319
335
  test_files: []