kuber_kit 0.4.9 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/Gemfile.lock +2 -2
  4. data/TODO.md +5 -5
  5. data/example/configurations/review.rb +1 -1
  6. data/example/services/ruby_app.rb +1 -0
  7. data/lib/kuber_kit.rb +9 -0
  8. data/lib/kuber_kit/actions/kubectl_attacher.rb +2 -2
  9. data/lib/kuber_kit/actions/kubectl_console.rb +2 -2
  10. data/lib/kuber_kit/actions/kubectl_describe.rb +2 -2
  11. data/lib/kuber_kit/actions/kubectl_env.rb +19 -0
  12. data/lib/kuber_kit/actions/kubectl_get.rb +32 -0
  13. data/lib/kuber_kit/actions/kubectl_logs.rb +2 -2
  14. data/lib/kuber_kit/actions/service_checker.rb +37 -0
  15. data/lib/kuber_kit/actions/service_deployer.rb +79 -60
  16. data/lib/kuber_kit/cli.rb +28 -1
  17. data/lib/kuber_kit/configs.rb +2 -1
  18. data/lib/kuber_kit/container.rb +20 -0
  19. data/lib/kuber_kit/core/configuration.rb +4 -2
  20. data/lib/kuber_kit/core/configuration_definition.rb +7 -0
  21. data/lib/kuber_kit/core/configuration_factory.rb +1 -0
  22. data/lib/kuber_kit/core/dependencies/abstract_dependency_resolver.rb +75 -0
  23. data/lib/kuber_kit/core/image.rb +2 -1
  24. data/lib/kuber_kit/core/service.rb +4 -2
  25. data/lib/kuber_kit/core/service_definition.rb +13 -6
  26. data/lib/kuber_kit/core/service_factory.rb +1 -0
  27. data/lib/kuber_kit/image_compiler/image_dependency_resolver.rb +5 -53
  28. data/lib/kuber_kit/kubernetes/resource_selector.rb +33 -0
  29. data/lib/kuber_kit/kubernetes/resources_fetcher.rb +7 -30
  30. data/lib/kuber_kit/service_deployer/service_dependency_resolver.rb +14 -0
  31. data/lib/kuber_kit/service_deployer/service_list_resolver.rb +11 -6
  32. data/lib/kuber_kit/service_deployer/strategies/kubernetes.rb +9 -2
  33. data/lib/kuber_kit/shell/commands/kubectl_commands.rb +12 -4
  34. data/lib/kuber_kit/shell/local_shell.rb +15 -1
  35. data/lib/kuber_kit/version.rb +1 -1
  36. metadata +9 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 766eae8b402b82c6e307942d24f2ee60d87197ef0b966f8551e17b2926a8210b
4
- data.tar.gz: eae14447e34ab527affdfbbbdd9b34027470b6c2b54b63bb27be8cdf651bbd27
3
+ metadata.gz: 2e99c1ae700ec8b59f9a832d3c9131e85c7d05a60548d8bca032d4ce2c9178b2
4
+ data.tar.gz: e4233e8cf40a7980477d85f341320536725efd169ac4120e74de6c7ad651e436
5
5
  SHA512:
6
- metadata.gz: '086f8e0c1983f00c3b517d4bf8a90c53d4ba58395b429d65a0dd2afeb8e80aae0e5120adf3ea1936b3f7c343de57378ef4e6e5b45c4836eb3de82f73a8198bc7'
7
- data.tar.gz: d236328533a9f15eba54dba8c777e54821ddab141aaf46ada97e88d35a7fc7fe7048bcb49ddb719b081d55a36883a8434c39632343a210b174343851eb43fa93
6
+ metadata.gz: 10a3f4b72a0d3a09c9a49842642e6f7a0457a5cb243d0c469c9792c7fcc70ff483b9ffbd6ecc7c278d20b3b7e22f603e45ad3360e701b1a9cf9696cff64d46ce
7
+ data.tar.gz: f857ce1a307375486c51cfaa67c22a929826b54a1ad572dc5a5ac64fb4febfe680fa27f3adddadf2d2b3d68325cd5dee7ba47facdf672c427640d048c23c950f
data/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ **0.5.4**
2
+ - Added disabled services support
3
+
4
+ **0.5.3**
5
+ - Change the symbol to exclude service from "-" to "!", you can pass "-s !auth_app" to exclude "auth_app"
6
+ - Added kit get command to find pods
7
+
8
+ **0.5.2**
9
+ - Added dependencies support to services
10
+ - Added an option to deploy all services in `kit deloy`
11
+ - Wait for rollout to finish during service deploy
12
+ - Deploy services in batches, not all of the simultaneously
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kuber_kit (0.4.9)
4
+ kuber_kit (0.5.4)
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,8 +1,8 @@
1
- - do not show result for images list, if list is too large (Mikhail)
2
- - add kit get method for interactive kubernetes
3
- - kit status should show the list of services and their status, with ability to select & view logs
4
- - find a way to always deploy some service, e.g. for migrations and env_files
1
+ - add kit get method for more interactive kubernetes
2
+ - env files should use a separate deployment method (with change detection)
3
+ - add automatical confirmation support for service deployer
5
4
  - template should be able to set default attributes
6
5
  - template should be able to depend on image?
7
6
  - cleanup image builds older than some date
8
- - add some rotation for deploy log
7
+ - add some rotation for deploy log
8
+ - kit status should show the list of services and their status, with ability to select & view logs
@@ -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)
@@ -1,5 +1,6 @@
1
1
  KuberKit
2
2
  .define_service(:ruby_app)
3
+ .depends_on(:env_file)
3
4
  .template(:service)
4
5
  .images(:ruby_app)
5
6
  .tags("app")
data/lib/kuber_kit.rb CHANGED
@@ -46,6 +46,10 @@ module KuberKit
46
46
  autoload :BuildServer, 'core/build_servers/build_server'
47
47
  end
48
48
 
49
+ module Dependencies
50
+ autoload :AbstractDependencyResolver, 'core/dependencies/abstract_dependency_resolver'
51
+ end
52
+
49
53
  module EnvFiles
50
54
  autoload :EnvFileStore, 'core/env_files/env_file_store'
51
55
  autoload :AbstractEnvFile, 'core/env_files/abstract_env_file'
@@ -145,6 +149,7 @@ module KuberKit
145
149
  autoload :StrategyDetector, 'service_deployer/strategy_detector'
146
150
  autoload :Deployer, 'service_deployer/deployer'
147
151
  autoload :ServiceListResolver, 'service_deployer/service_list_resolver'
152
+ autoload :ServiceDependencyResolver, 'service_deployer/service_dependency_resolver'
148
153
 
149
154
  module Strategies
150
155
  autoload :Abstract, 'service_deployer/strategies/abstract'
@@ -165,12 +170,15 @@ module KuberKit
165
170
  autoload :TemplateReader, 'actions/template_reader'
166
171
  autoload :ServiceReader, 'actions/service_reader'
167
172
  autoload :ServiceDeployer, 'actions/service_deployer'
173
+ autoload :ServiceChecker, 'actions/service_checker'
168
174
  autoload :ConfigurationLoader, 'actions/configuration_loader'
169
175
  autoload :KubectlApplier, 'actions/kubectl_applier'
170
176
  autoload :KubectlAttacher, 'actions/kubectl_attacher'
171
177
  autoload :KubectlConsole, 'actions/kubectl_console'
172
178
  autoload :KubectlDescribe, 'actions/kubectl_describe'
179
+ autoload :KubectlGet, 'actions/kubectl_get'
173
180
  autoload :KubectlLogs, 'actions/kubectl_logs'
181
+ autoload :KubectlEnv, 'actions/kubectl_env'
174
182
  end
175
183
 
176
184
  module Extensions
@@ -178,6 +186,7 @@ module KuberKit
178
186
  end
179
187
 
180
188
  module Kubernetes
189
+ autoload :ResourceSelector, 'kubernetes/resource_selector'
181
190
  autoload :ResourcesFetcher, 'kubernetes/resources_fetcher'
182
191
  end
183
192
 
@@ -2,7 +2,7 @@ class KuberKit::Actions::KubectlAttacher
2
2
  include KuberKit::Import[
3
3
  "shell.kubectl_commands",
4
4
  "shell.local_shell",
5
- "kubernetes.resources_fetcher",
5
+ "kubernetes.resource_selector",
6
6
  "ui"
7
7
  ]
8
8
 
@@ -12,7 +12,7 @@ class KuberKit::Actions::KubectlAttacher
12
12
  deployer_namespace = KuberKit.current_configuration.deployer_namespace
13
13
 
14
14
  if !pod_name
15
- pod_name = resources_fetcher.call("attach")
15
+ pod_name = resource_selector.call("attach")
16
16
  end
17
17
 
18
18
  kubectl_commands.exec(
@@ -2,7 +2,7 @@ class KuberKit::Actions::KubectlConsole
2
2
  include KuberKit::Import[
3
3
  "shell.kubectl_commands",
4
4
  "shell.local_shell",
5
- "kubernetes.resources_fetcher",
5
+ "kubernetes.resource_selector",
6
6
  "ui"
7
7
  ]
8
8
 
@@ -12,7 +12,7 @@ class KuberKit::Actions::KubectlConsole
12
12
  deployer_namespace = KuberKit.current_configuration.deployer_namespace
13
13
 
14
14
  if !pod_name
15
- pod_name = resources_fetcher.call("attach")
15
+ pod_name = resource_selector.call("attach")
16
16
  end
17
17
 
18
18
  kubectl_commands.exec(
@@ -2,7 +2,7 @@ class KuberKit::Actions::KubectlDescribe
2
2
  include KuberKit::Import[
3
3
  "shell.kubectl_commands",
4
4
  "shell.local_shell",
5
- "kubernetes.resources_fetcher",
5
+ "kubernetes.resource_selector",
6
6
  "ui"
7
7
  ]
8
8
 
@@ -12,7 +12,7 @@ class KuberKit::Actions::KubectlDescribe
12
12
  deployer_namespace = KuberKit.current_configuration.deployer_namespace
13
13
 
14
14
  if !resource_name
15
- resource_name = resources_fetcher.call("describe", include_ingresses: true, include_pods: true)
15
+ resource_name = resource_selector.call("describe", include_ingresses: true, include_pods: true)
16
16
  end
17
17
 
18
18
  args = nil
@@ -0,0 +1,19 @@
1
+ class KuberKit::Actions::KubectlEnv
2
+ include KuberKit::Import[
3
+ "shell.local_shell",
4
+ "ui"
5
+ ]
6
+
7
+ Contract Hash => Any
8
+ def call(options)
9
+ configuration = KuberKit.current_configuration
10
+ kubeconfig_path = configuration.kubeconfig_path
11
+ ui.print_info("ENV", "export KUBECONFIG=#{kubeconfig_path}")
12
+
13
+ true
14
+ rescue KuberKit::Error => e
15
+ ui.print_error("Error", e.message)
16
+
17
+ false
18
+ end
19
+ end
@@ -0,0 +1,32 @@
1
+ class KuberKit::Actions::KubectlGet
2
+ include KuberKit::Import[
3
+ "shell.kubectl_commands",
4
+ "shell.local_shell",
5
+ "kubernetes.resource_selector",
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
+ resources = kubectl_commands.get_resources(
15
+ local_shell, "pod",
16
+ kubeconfig_path: kubeconfig_path,
17
+ namespace: deployer_namespace
18
+ )
19
+
20
+ if resource_name
21
+ resources = resources.select{|r| r.include?(resource_name) }
22
+ end
23
+
24
+ ui.print_info("Pods", resources.join("\n"))
25
+
26
+ true
27
+ rescue KuberKit::Error => e
28
+ ui.print_error("Error", e.message)
29
+
30
+ false
31
+ end
32
+ end
@@ -2,7 +2,7 @@ class KuberKit::Actions::KubectlLogs
2
2
  include KuberKit::Import[
3
3
  "shell.kubectl_commands",
4
4
  "shell.local_shell",
5
- "kubernetes.resources_fetcher",
5
+ "kubernetes.resource_selector",
6
6
  "ui"
7
7
  ]
8
8
 
@@ -12,7 +12,7 @@ class KuberKit::Actions::KubectlLogs
12
12
  deployer_namespace = KuberKit.current_configuration.deployer_namespace
13
13
 
14
14
  if !pod_name
15
- pod_name = resources_fetcher.call("attach")
15
+ pod_name = resource_selector.call("attach")
16
16
  end
17
17
 
18
18
  args = nil
@@ -0,0 +1,37 @@
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
+ disabled_services = KuberKit.current_configuration.disabled_services.map(&:to_s)
19
+ if disabled_services.any?
20
+ services = services.select{ |s| !disabled_services.include?(s) }
21
+ end
22
+
23
+ resources = resources_fetcher.call("deployments") + resources_fetcher.call("cronjobs")
24
+
25
+ missing_services = services.select{ |s| !resources.include?(s.gsub("_", "-")) }
26
+
27
+ ui.print_warning("Warning", "This command will only check services deployed using k8s")
28
+
29
+ ui.print_info("Missing", missing_services.inspect)
30
+
31
+ {}
32
+ rescue KuberKit::Error => e
33
+ ui.print_error("Error", e.message)
34
+
35
+ false
36
+ end
37
+ end
@@ -2,9 +2,11 @@ class KuberKit::Actions::ServiceDeployer
2
2
  include KuberKit::Import[
3
3
  "actions.image_compiler",
4
4
  "service_deployer.service_list_resolver",
5
+ "service_deployer.service_dependency_resolver",
5
6
  "core.service_store",
6
7
  "shell.local_shell",
7
8
  "tools.process_cleaner",
9
+ "configs",
8
10
  "ui",
9
11
  service_deployer: "service_deployer.action_handler",
10
12
  ]
@@ -16,6 +18,8 @@ class KuberKit::Actions::ServiceDeployer
16
18
  require_confirmation: Maybe[Bool],
17
19
  ] => Any
18
20
  def call(services:, tags:, skip_compile: false, require_confirmation: false)
21
+ current_configuration = KuberKit.current_configuration
22
+
19
23
  if services.empty? && tags.empty?
20
24
  services, tags = show_tags_selection
21
25
  end
@@ -23,15 +27,19 @@ class KuberKit::Actions::ServiceDeployer
23
27
  service_names = service_list_resolver.resolve(
24
28
  services: services || [],
25
29
  tags: tags || [],
26
- enabled_services: KuberKit.current_configuration.enabled_services.map(&:to_s)
27
- )
30
+ enabled_services: current_configuration.enabled_services.map(&:to_s),
31
+ disabled_services: current_configuration.disabled_services.map(&:to_s)
32
+ ).map(&:to_sym)
33
+
34
+ # Return the list of services with all dependencies.
35
+ all_service_names = service_dependency_resolver.get_all(service_names)
28
36
 
29
- unless service_names.any?
37
+ unless all_service_names.any?
30
38
  ui.print_warning "ServiceDeployer", "No service found with given options, nothing will be deployed."
31
39
  return false
32
40
  end
33
41
 
34
- services_list = service_names.map(&:to_s).map(&:yellow).join(", ")
42
+ services_list = all_service_names.map(&:to_s).map(&:yellow).join(", ")
35
43
  ui.print_info "ServiceDeployer", "The following services will be deployed: #{services_list}"
36
44
 
37
45
  if require_confirmation
@@ -39,7 +47,7 @@ class KuberKit::Actions::ServiceDeployer
39
47
  return false unless ["confirm".green, "confirm", "yes"].include?(result)
40
48
  end
41
49
 
42
- services = service_names.map do |service_name|
50
+ services = all_service_names.map do |service_name|
43
51
  service_store.get_service(service_name.to_sym)
44
52
  end
45
53
 
@@ -50,9 +58,16 @@ class KuberKit::Actions::ServiceDeployer
50
58
  return false unless compile_result
51
59
  end
52
60
 
53
- deployment_result = deploy_services(service_names)
61
+ deployed_services = []
62
+ deployment_result = {}
63
+ service_dependency_resolver.each_with_deps(service_names) do |dep_service_names|
64
+ ui.print_debug("ServiceDeployer", "Scheduling to compile: #{dep_service_names.inspect}. Limit: #{configs.deploy_simultaneous_limit}")
65
+ result = deploy_simultaneously(dep_service_names)
66
+ deployed_services += dep_service_names
67
+ deployment_result = deployment_result.merge(result)
68
+ end
54
69
 
55
- { services: service_names, deployment: deployment_result }
70
+ { services: all_service_names, deployment: deployment_result }
56
71
  rescue KuberKit::Error => e
57
72
  ui.print_error("Error", e.message)
58
73
 
@@ -61,69 +76,73 @@ class KuberKit::Actions::ServiceDeployer
61
76
  process_cleaner.clean
62
77
  end
63
78
 
64
- def deploy_services(service_names)
65
- task_group = ui.create_task_group
79
+ private
80
+ def deploy_simultaneously(service_names)
81
+ task_group = ui.create_task_group
66
82
 
67
- deployer_result = {}
83
+ deployer_result = {}
68
84
 
69
- service_names.each do |service_name|
85
+ service_names.each do |service_name|
70
86
 
71
- ui.print_debug("ServiceDeployer", "Started deploying: #{service_name.to_s.green}")
72
- task_group.add("Deploying #{service_name.to_s.yellow}") do |task|
73
- deployer_result[service_name] = service_deployer.call(local_shell, service_name.to_sym)
87
+ ui.print_debug("ServiceDeployer", "Started deploying: #{service_name.to_s.green}")
88
+ task_group.add("Deploying #{service_name.to_s.yellow}") do |task|
89
+ deployer_result[service_name] = service_deployer.call(local_shell, service_name.to_sym)
74
90
 
75
- task.update_title("Deployed #{service_name.to_s.green}")
76
- ui.print_debug("ServiceDeployer", "Finished deploying: #{service_name.to_s.green}")
91
+ task.update_title("Deployed #{service_name.to_s.green}")
92
+ ui.print_debug("ServiceDeployer", "Finished deploying: #{service_name.to_s.green}")
93
+ end
77
94
  end
78
- end
79
95
 
80
- task_group.wait
96
+ task_group.wait
81
97
 
82
- deployer_result
83
- end
84
-
85
- def compile_images(images_names)
86
- return true if images_names.empty?
87
- image_compiler.call(images_names, {})
88
- end
98
+ deployer_result
99
+ end
89
100
 
90
- def show_tags_selection()
91
- specific_service_option = "deploy specific service"
92
-
93
- tags = [specific_service_option]
94
- tags += service_store
95
- .all_definitions
96
- .values
97
- .map(&:to_service_attrs)
98
- .map(&:tags)
99
- .flatten
100
- .uniq
101
- .sort
102
- .map(&:to_s)
103
-
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
+ def compile_images(images_names)
102
+ return true if images_names.empty?
103
+ image_compiler.call(images_names, {})
110
104
  end
111
- end
112
105
 
113
- def show_service_selection()
114
- services = service_store
115
- .all_definitions
116
- .values
117
- .map(&:service_name)
118
- .uniq
119
- .sort
120
- .map(&:to_s)
121
-
122
- if services.empty?
123
- return [[], []]
106
+ def show_tags_selection()
107
+ specific_service_option = "deploy specific service"
108
+ all_services_option = "deploy all services"
109
+
110
+ tags = [specific_service_option, all_services_option]
111
+ tags += service_store
112
+ .all_definitions
113
+ .values
114
+ .map(&:to_service_attrs)
115
+ .map(&:tags)
116
+ .flatten
117
+ .uniq
118
+ .sort
119
+ .map(&:to_s)
120
+
121
+ selected_tag = ui.prompt("Please select which tag to deploy", tags)
122
+
123
+ if selected_tag == specific_service_option
124
+ show_service_selection
125
+ elsif selected_tag == all_services_option
126
+ [["*"], []]
127
+ else
128
+ [[], [selected_tag]]
129
+ end
124
130
  end
125
131
 
126
- selected_service = ui.prompt("Please select which service to deploy", services)
127
- [[selected_service], []]
128
- end
132
+ def show_service_selection()
133
+ services = service_store
134
+ .all_definitions
135
+ .values
136
+ .map(&:service_name)
137
+ .uniq
138
+ .sort
139
+ .map(&:to_s)
140
+
141
+ if services.empty?
142
+ return [[], []]
143
+ end
144
+
145
+ selected_service = ui.prompt("Please select which service to deploy", services)
146
+ [[selected_service], []]
147
+ end
129
148
  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 -t CONTEXT_NAME", "Deploy CONTEXT_NAME with kubectl"
33
+ desc "deploy -t TAG_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"]
@@ -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,24 @@ 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
+
153
+ desc "get RESOURCE_NAME", "List pods matching RESOURCE_NAME using kubectl"
154
+ def get(pod_name = nil)
155
+ setup(options)
156
+
157
+ if KuberKit::Container['actions.configuration_loader'].call(options.merge(load_inventory: false))
158
+ KuberKit::Container['actions.kubectl_get'].call(pod_name, options)
159
+ end
160
+ end
161
+
135
162
  desc "version", "Print current version"
136
163
  def version
137
164
  puts KuberKit::VERSION
@@ -4,7 +4,7 @@ class KuberKit::Configs
4
4
  AVAILABLE_CONFIGS = [
5
5
  :image_dockerfile_name, :image_build_context_dir, :image_tag, :docker_ignore_list, :image_compile_dir,
6
6
  :kuber_kit_dirname, :kuber_kit_min_version, :images_dirname, :services_dirname, :infra_dirname, :configurations_dirname,
7
- :artifact_clone_dir, :service_config_dir, :deployer_strategy, :compile_simultaneous_limit,
7
+ :artifact_clone_dir, :service_config_dir, :deployer_strategy, :compile_simultaneous_limit, :deploy_simultaneous_limit,
8
8
  :additional_images_paths, :deprecation_warnings_disabled, :log_file_path
9
9
  ]
10
10
  DOCKER_IGNORE_LIST = [
@@ -49,6 +49,7 @@ class KuberKit::Configs
49
49
  set :service_config_dir, "/tmp/kuber_kit/services"
50
50
  set :deployer_strategy, :kubernetes
51
51
  set :compile_simultaneous_limit, 5
52
+ set :deploy_simultaneous_limit, 5
52
53
  set :additional_images_paths, []
53
54
  set :deprecation_warnings_disabled, false
54
55
  set :log_file_path, "/tmp/kuber_kit.log"
@@ -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
@@ -41,10 +45,18 @@ class KuberKit::Container
41
45
  KuberKit::Actions::KubectlDescribe.new
42
46
  end
43
47
 
48
+ register "actions.kubectl_get" do
49
+ KuberKit::Actions::KubectlGet.new
50
+ end
51
+
44
52
  register "actions.kubectl_logs" do
45
53
  KuberKit::Actions::KubectlLogs.new
46
54
  end
47
55
 
56
+ register "actions.kubectl_env" do
57
+ KuberKit::Actions::KubectlEnv.new
58
+ end
59
+
48
60
  register "configs" do
49
61
  KuberKit::Configs.new
50
62
  end
@@ -249,6 +261,10 @@ class KuberKit::Container
249
261
  KuberKit::ServiceDeployer::ServiceListResolver.new
250
262
  end
251
263
 
264
+ register "service_deployer.service_dependency_resolver" do
265
+ KuberKit::ServiceDeployer::ServiceDependencyResolver.new
266
+ end
267
+
252
268
  register "service_deployer.strategies.kubernetes" do
253
269
  KuberKit::ServiceDeployer::Strategies::Kubernetes.new
254
270
  end
@@ -269,6 +285,10 @@ class KuberKit::Container
269
285
  KuberKit::ServiceReader::Reader.new
270
286
  end
271
287
 
288
+ register "kubernetes.resource_selector" do
289
+ KuberKit::Kubernetes::ResourceSelector.new
290
+ end
291
+
272
292
  register "kubernetes.resources_fetcher" do
273
293
  KuberKit::Kubernetes::ResourcesFetcher.new
274
294
  end
@@ -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, :enabled_services, :build_servers, :global_build_vars,
3
+ :services_attributes, :enabled_services, :disabled_services, :build_servers, :global_build_vars,
4
4
  :deployer_strategy, :deployer_namespace, :deployer_require_confirimation
5
5
 
6
6
  Contract KeywordArgs[
@@ -12,6 +12,7 @@ class KuberKit::Core::Configuration
12
12
  kubeconfig_path: Maybe[String],
13
13
  services_attributes: HashOf[Symbol => Hash],
14
14
  enabled_services: ArrayOf[Symbol],
15
+ disabled_services: ArrayOf[Symbol],
15
16
  build_servers: ArrayOf[KuberKit::Core::BuildServers::AbstractBuildServer],
16
17
  global_build_vars: HashOf[Symbol => Any],
17
18
  deployer_strategy: Symbol,
@@ -19,7 +20,7 @@ class KuberKit::Core::Configuration
19
20
  deployer_require_confirimation: Bool,
20
21
  ] => Any
21
22
  def initialize(name:, artifacts:, registries:, env_files:, templates:, kubeconfig_path:,
22
- services_attributes:, enabled_services:, build_servers:, global_build_vars:,
23
+ services_attributes:, enabled_services:, disabled_services:, build_servers:, global_build_vars:,
23
24
  deployer_strategy:, deployer_namespace:, deployer_require_confirimation:)
24
25
  @name = name
25
26
  @artifacts = artifacts
@@ -30,6 +31,7 @@ class KuberKit::Core::Configuration
30
31
  @build_servers = build_servers
31
32
  @services_attributes = services_attributes
32
33
  @enabled_services = enabled_services
34
+ @disabled_services = disabled_services
33
35
  @global_build_vars = global_build_vars
34
36
  @deployer_strategy = deployer_strategy
35
37
  @deployer_namespace = deployer_namespace
@@ -12,6 +12,7 @@ class KuberKit::Core::ConfigurationDefinition
12
12
  @templates = {}
13
13
  @build_servers = []
14
14
  @enabled_services = []
15
+ @disabled_services = []
15
16
  @services_attributes = {}
16
17
  end
17
18
 
@@ -24,6 +25,7 @@ class KuberKit::Core::ConfigurationDefinition
24
25
  templates: @templates,
25
26
  kubeconfig_path: @kubeconfig_path,
26
27
  enabled_services: @enabled_services,
28
+ disabled_services: @disabled_services,
27
29
  build_servers: @build_servers,
28
30
  services_attributes: @services_attributes,
29
31
  global_build_vars: @global_build_vars,
@@ -116,6 +118,11 @@ class KuberKit::Core::ConfigurationDefinition
116
118
  raise KuberKit::Error, "#enabled_services method accepts only Array or Hash"
117
119
  end
118
120
 
121
+ def disabled_services(services)
122
+ @disabled_services += services.map(&:to_sym)
123
+ return self
124
+ end
125
+
119
126
  def service_attributes(services)
120
127
  @services_attributes = @services_attributes.merge(services)
121
128
  self
@@ -29,6 +29,7 @@ class KuberKit::Core::ConfigurationFactory
29
29
  build_servers: build_servers,
30
30
  services_attributes: configuration_attrs.services_attributes,
31
31
  enabled_services: configuration_attrs.enabled_services,
32
+ disabled_services: configuration_attrs.disabled_services,
32
33
  global_build_vars: configuration_attrs.global_build_vars || {},
33
34
  deployer_strategy: configuration_attrs.deployer_strategy || configs.deployer_strategy,
34
35
  deployer_namespace: configuration_attrs.deployer_namespace,
@@ -0,0 +1,75 @@
1
+ class KuberKit::Core::Dependencies::AbstractDependencyResolver
2
+ CircularDependencyError = Class.new(KuberKit::Error)
3
+ DependencyNotFoundError = Class.new(KuberKit::NotFoundError)
4
+
5
+ # Iterate over list of dependencies for items (including the items themself).
6
+ # Iteration will send the list to the callback block function
7
+ Contract Or[Symbol, ArrayOf[Symbol]], Proc => Any
8
+ def each_with_deps(item_names, &block)
9
+ resolved_dependencies = []
10
+ # Get first list of dependencies ready to resolve
11
+ next_dependencies = get_next(item_names, limit: dependency_batch_size)
12
+
13
+ # Call the block for each list of dependencies ready to resolve, then calculate the next list
14
+ while (next_dependencies - resolved_dependencies).any?
15
+ block.call(next_dependencies)
16
+ resolved_dependencies += next_dependencies
17
+ next_dependencies = get_next(item_names, resolved: resolved_dependencies, limit: dependency_batch_size)
18
+ end
19
+
20
+ (item_names - resolved_dependencies).each_slice(dependency_batch_size) do |group|
21
+ block.call(group)
22
+ end
23
+ end
24
+
25
+ # Returns next list of dependencies ready to resolve.
26
+ # Item is not ready to resolve if it has personal dependency.
27
+ # E.g. if "A" depends on "B" and "C", "C" depends on "D", then only "B" and "D" will be returned.
28
+ Contract Or[Symbol, ArrayOf[Symbol]], KeywordArgs[
29
+ resolved: Optional[ArrayOf[Symbol]],
30
+ limit: Optional[Maybe[Num]]
31
+ ] => Any
32
+ def get_next(item_names, resolved: [], limit: nil)
33
+ deps = Array(item_names).map { |i| get_recursive_deps(i) }.flatten.uniq
34
+
35
+ # Find out which dependencies are ready to resolve,
36
+ # they should not have unresolved personal dependencies
37
+ ready_to_resolve = deps.select do |dep_name|
38
+ unresolved_deps = get_deps(dep_name) - resolved
39
+ unresolved_deps.empty?
40
+ end
41
+ unresolved_deps = ready_to_resolve - resolved
42
+ unresolved_deps = unresolved_deps.take(limit) if limit
43
+ unresolved_deps
44
+ end
45
+
46
+ # Get all dependencies for items (including the items themself), without any limitations
47
+ Contract Or[Symbol, ArrayOf[Symbol]] => Any
48
+ def get_all(item_names)
49
+ deps = Array(item_names).map { |i| get_recursive_deps(i) }.flatten
50
+ (deps + item_names).uniq
51
+ end
52
+
53
+ def get_recursive_deps(item_name, dependency_tree: [])
54
+ deps = get_deps(item_name)
55
+
56
+ if dependency_tree.include?(item_name)
57
+ raise CircularDependencyError, "Circular dependency found for #{item_name}. Dependency tree: #{dependency_tree.inspect}"
58
+ end
59
+
60
+ child_deps = []
61
+ deps.each do |i|
62
+ child_deps += get_recursive_deps(i, dependency_tree: dependency_tree + [item_name])
63
+ end
64
+
65
+ (deps + child_deps).uniq
66
+ end
67
+
68
+ def get_deps(item_name)
69
+ raise "This method should be overriden"
70
+ end
71
+
72
+ def dependency_batch_size
73
+ raise "This method should be overriden"
74
+ end
75
+ end
@@ -1,5 +1,6 @@
1
1
  class KuberKit::Core::Image
2
- attr_reader :name, :dependencies, :registry, :dockerfile_path, :build_vars, :build_context_dir, :tag, :before_build_callback, :after_build_callback
2
+ attr_reader :name, :dependencies, :registry, :dockerfile_path, :build_vars, :build_context_dir, :tag,
3
+ :before_build_callback, :after_build_callback
3
4
 
4
5
  Contract KeywordArgs[
5
6
  name: Symbol,
@@ -1,18 +1,20 @@
1
1
  class KuberKit::Core::Service
2
2
  AttributeNotSet = Class.new(Indocker::Error)
3
3
 
4
- attr_reader :name, :template_name, :tags, :images, :attributes, :deployer_strategy
4
+ attr_reader :name, :dependencies, :template_name, :tags, :images, :attributes, :deployer_strategy
5
5
 
6
6
  Contract KeywordArgs[
7
7
  name: Symbol,
8
+ dependencies: ArrayOf[Symbol],
8
9
  template_name: Maybe[Symbol],
9
10
  tags: ArrayOf[Symbol],
10
11
  images: ArrayOf[Symbol],
11
12
  attributes: HashOf[Symbol => Any],
12
13
  deployer_strategy: Maybe[Symbol]
13
14
  ] => Any
14
- def initialize(name:, template_name:, tags:, images:, attributes:, deployer_strategy:)
15
+ def initialize(name:, dependencies:, template_name:, tags:, images:, attributes:, deployer_strategy:)
15
16
  @name = name
17
+ @dependencies = dependencies
16
18
  @template_name = template_name
17
19
  @tags = tags
18
20
  @images = images
@@ -1,22 +1,29 @@
1
1
  class KuberKit::Core::ServiceDefinition
2
- attr_reader :service_name, :template_name
2
+ attr_reader :service_name, :template_name, :dependencies
3
3
 
4
4
  Contract Or[Symbol, String] => Any
5
5
  def initialize(service_name)
6
6
  @service_name = service_name.to_sym
7
+ @dependencies = []
7
8
  end
8
9
 
9
10
  def to_service_attrs
10
11
  OpenStruct.new(
11
- name: @service_name,
12
- template_name: get_value(@template_name),
13
- tags: Array(get_value(@tags)).map(&:to_sym),
14
- images: Array(get_value(@images)).map(&:to_sym),
15
- attributes: get_value(@attributes),
12
+ name: @service_name,
13
+ dependencies: @dependencies,
14
+ template_name: get_value(@template_name),
15
+ tags: Array(get_value(@tags)).map(&:to_sym),
16
+ images: Array(get_value(@images)).map(&:to_sym),
17
+ attributes: get_value(@attributes),
16
18
  deployer_strategy: get_value(@deployer_strategy),
17
19
  )
18
20
  end
19
21
 
22
+ def depends_on(*value, &block)
23
+ @dependencies = Array(value).flatten
24
+ self
25
+ end
26
+
20
27
  def template(value = nil, &block)
21
28
  @template_name = block_given? ? block : value
22
29
 
@@ -7,6 +7,7 @@ class KuberKit::Core::ServiceFactory
7
7
 
8
8
  KuberKit::Core::Service.new(
9
9
  name: service_attrs.name,
10
+ dependencies: service_attrs.dependencies,
10
11
  template_name: service_attrs.template_name,
11
12
  tags: service_attrs.tags,
12
13
  images: service_attrs.images,
@@ -1,62 +1,14 @@
1
- class KuberKit::ImageCompiler::ImageDependencyResolver
2
- CircularDependencyError = Class.new(KuberKit::Error)
3
- DependencyNotFoundError = Class.new(KuberKit::NotFoundError)
4
-
1
+ class KuberKit::ImageCompiler::ImageDependencyResolver < KuberKit::Core::Dependencies::AbstractDependencyResolver
5
2
  include KuberKit::Import[
6
3
  "core.image_store",
7
4
  "configs"
8
5
  ]
9
-
10
- Contract Or[Symbol, ArrayOf[Symbol]], Proc => Any
11
- def each_with_deps(image_names, &block)
12
- compile_limit = configs.compile_simultaneous_limit
13
-
14
- resolved_dependencies = []
15
- next_dependencies = get_next(image_names, limit: compile_limit)
16
-
17
- while (next_dependencies - resolved_dependencies).any?
18
- block.call(next_dependencies)
19
- resolved_dependencies += next_dependencies
20
- next_dependencies = get_next(image_names, resolved: resolved_dependencies, limit: compile_limit)
21
- end
22
-
23
- (image_names - resolved_dependencies).each_slice(compile_limit) do |group|
24
- block.call(group)
25
- end
26
- end
27
6
 
28
- Contract Or[Symbol, ArrayOf[Symbol]], KeywordArgs[
29
- resolved: Optional[ArrayOf[Symbol]],
30
- limit: Optional[Maybe[Num]]
31
- ] => Any
32
- def get_next(image_names, resolved: [], limit: nil)
33
- deps = Array(image_names).map { |i| get_recursive_deps(i) }.flatten.uniq
34
-
35
- ready_to_resolve = deps.select do |dep_name|
36
- unresolved_deps = get_deps(dep_name) - resolved
37
- unresolved_deps.empty?
38
- end
39
- unresolved_deps = ready_to_resolve - resolved
40
- unresolved_deps = unresolved_deps.take(limit) if limit
41
- unresolved_deps
42
- end
43
-
44
- def get_recursive_deps(image_name, dependency_tree: [])
45
- deps = get_deps(image_name)
46
-
47
- if dependency_tree.include?(image_name)
48
- raise CircularDependencyError, "Circular dependency found for #{image_name}. Dependency tree: #{dependency_tree.inspect}"
49
- end
50
-
51
- child_deps = []
52
- deps.each do |i|
53
- child_deps += get_recursive_deps(i, dependency_tree: dependency_tree + [image_name])
54
- end
55
-
56
- (deps + child_deps).uniq
57
- end
58
-
59
7
  def get_deps(image_name)
60
8
  image_store.get_definition(image_name).dependencies
61
9
  end
10
+
11
+ def dependency_batch_size
12
+ configs.compile_simultaneous_limit
13
+ end
62
14
  end
@@ -0,0 +1,33 @@
1
+ class KuberKit::Kubernetes::ResourceSelector
2
+ include KuberKit::Import[
3
+ "kubernetes.resources_fetcher",
4
+ "shell.local_shell",
5
+ "ui"
6
+ ]
7
+
8
+ Contract String, KeywordArgs[
9
+ include_ingresses: Optional[Bool],
10
+ include_pods: Optional[Bool]
11
+ ] => Any
12
+ def call(action_name, include_ingresses: false, include_pods: false)
13
+ deployments = resources_fetcher.call("deployments")
14
+ options = deployments.map{|d| "deploy/#{d}" }
15
+ options << "ingresses" if include_ingresses
16
+ options << "pods" if include_pods
17
+ option = ui.prompt("Please select resource to #{action_name}", options)
18
+
19
+ if option == "ingresses" && include_ingresses
20
+ ingresses = resources_fetcher.call("ingresses")
21
+ options = ingresses.map{|d| "ingresses/#{d}" }
22
+ return ui.prompt("Please select ingress to #{action_name}", options)
23
+ end
24
+
25
+ if option == "pods" && include_pods
26
+ ingresses = resources_fetcher.call("pods")
27
+ options = ingresses.map{|d| "pods/#{d}" }
28
+ return ui.prompt("Please select pod to #{action_name}", options)
29
+ end
30
+
31
+ option
32
+ end
33
+ end
@@ -2,40 +2,17 @@ class KuberKit::Kubernetes::ResourcesFetcher
2
2
  include KuberKit::Import[
3
3
  "shell.kubectl_commands",
4
4
  "shell.local_shell",
5
- "ui"
6
5
  ]
7
6
 
8
- Contract String, 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
7
+ Contract String => ArrayOf[String]
8
+ def call(resource_type)
9
+ current_configuration = KuberKit.current_configuration
30
10
 
31
- option
32
- end
33
-
34
- def get_resources(type)
35
11
  kubectl_commands.get_resources(
36
- local_shell, type,
37
- jsonpath: ".items[*].metadata.name",
38
- namespace: KuberKit.current_configuration.deployer_namespace
12
+ local_shell, resource_type,
13
+ jsonpath: ".items[*].metadata.name",
14
+ kubeconfig_path: current_configuration.kubeconfig_path,
15
+ namespace: current_configuration.deployer_namespace
39
16
  )
40
17
  end
41
18
  end
@@ -0,0 +1,14 @@
1
+ class KuberKit::ServiceDeployer::ServiceDependencyResolver < KuberKit::Core::Dependencies::AbstractDependencyResolver
2
+ include KuberKit::Import[
3
+ "core.service_store",
4
+ "configs"
5
+ ]
6
+
7
+ def get_deps(service_name)
8
+ service_store.get_definition(service_name).dependencies
9
+ end
10
+
11
+ def dependency_batch_size
12
+ configs.deploy_simultaneous_limit
13
+ end
14
+ end
@@ -4,11 +4,12 @@ class KuberKit::ServiceDeployer::ServiceListResolver
4
4
  ]
5
5
 
6
6
  Contract KeywordArgs[
7
- services: Optional[ArrayOf[String]],
8
- tags: Optional[ArrayOf[String]],
9
- enabled_services: Optional[ArrayOf[String]]
7
+ services: Optional[ArrayOf[String]],
8
+ tags: Optional[ArrayOf[String]],
9
+ enabled_services: Optional[ArrayOf[String]],
10
+ disabled_services: Optional[ArrayOf[String]]
10
11
  ] => ArrayOf[String]
11
- def resolve(services: [], tags: [], enabled_services: [])
12
+ def resolve(services: [], tags: [], enabled_services: [], disabled_services: [])
12
13
  all_definitions = service_store.all_definitions.values
13
14
 
14
15
  included_services, excluded_services = split_by_inclusion(services)
@@ -36,14 +37,18 @@ class KuberKit::ServiceDeployer::ServiceListResolver
36
37
  included_services = included_services.select{ |s| enabled_services.include?(s) }
37
38
  end
38
39
 
40
+ if disabled_services.any?
41
+ included_services = included_services.select{ |s| !disabled_services.include?(s) }
42
+ end
43
+
39
44
  included_services
40
45
  end
41
46
 
42
47
  Contract Array => Array
43
48
  def split_by_inclusion(array)
44
- excluded, included = array.partition{|e| e.start_with?('-') }
49
+ excluded, included = array.partition{|e| e.start_with?('!') }
45
50
 
46
- excluded.map!{ |item| item.gsub(/^\-/, "") }
51
+ excluded.map!{ |item| item.gsub(/^\!/, "") }
47
52
 
48
53
  [included, excluded]
49
54
  end
@@ -9,7 +9,8 @@ class KuberKit::ServiceDeployer::Strategies::Kubernetes < KuberKit::ServiceDeplo
9
9
  :resource_type,
10
10
  :resource_name,
11
11
  :delete_if_exists,
12
- :restart_if_exists
12
+ :restart_if_exists,
13
+ :wait_for_rollout
13
14
  ]
14
15
 
15
16
  Contract KuberKit::Shell::AbstractShell, KuberKit::Core::Service => Any
@@ -41,12 +42,18 @@ class KuberKit::ServiceDeployer::Strategies::Kubernetes < KuberKit::ServiceDeplo
41
42
 
42
43
  apply_result = kubectl_commands.apply_file(shell, config_path, kubeconfig_path: kubeconfig_path, namespace: namespace)
43
44
 
44
- restart_enabled = strategy_options.fetch(:restart_if_exists, true)
45
+ restart_enabled = strategy_options.fetch(:restart_if_exists, true)
46
+ wait_for_rollout = strategy_options.fetch(:wait_for_rollout, true)
45
47
  if restart_enabled && resource_exists
46
48
  kubectl_commands.rolling_restart(
47
49
  shell, resource_type, resource_name,
48
50
  kubeconfig_path: kubeconfig_path, namespace: namespace
49
51
  )
52
+
53
+ kubectl_commands.rollout_status(
54
+ shell, resource_type, resource_name, wait: true,
55
+ kubeconfig_path: kubeconfig_path, namespace: namespace
56
+ ) if wait_for_rollout
50
57
  end
51
58
 
52
59
  apply_result
@@ -60,19 +60,19 @@ class KuberKit::Shell::Commands::KubectlCommands
60
60
  command_parts << "-o jsonpath='{#{jsonpath}}'"
61
61
  end
62
62
 
63
- result = kubectl_run(shell, command_parts, kubeconfig_path: kubeconfig_path, namespace: namespace)
63
+ result = kubectl_run(shell, command_parts, kubeconfig_path: kubeconfig_path, namespace: namespace).to_s
64
64
 
65
65
  # Hide warnings manually, until appropriate kubectl option will be available
66
- result = result.split("\n").reject{|n| n.start_with?("Warning:") }.join("\n") 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)
@@ -102,4 +102,12 @@ class KuberKit::Shell::Commands::KubectlCommands
102
102
  }
103
103
  }, kubeconfig_path: kubeconfig_path, namespace: namespace)
104
104
  end
105
+
106
+ def rollout_status(shell, resource_type, resource_name, wait: true, kubeconfig_path: nil, namespace: nil)
107
+ command_parts = []
108
+ command_parts << %Q{rollout status #{resource_type} #{resource_name}}
109
+ command_parts << "-w" if wait
110
+
111
+ kubectl_run(shell, command_parts, kubeconfig_path: kubeconfig_path, namespace: namespace)
112
+ end
105
113
  end
@@ -1,6 +1,8 @@
1
1
  require 'fileutils'
2
2
 
3
3
  class KuberKit::Shell::LocalShell < KuberKit::Shell::AbstractShell
4
+ MAX_LINES_TO_PRINT = 50
5
+
4
6
  include KuberKit::Import[
5
7
  "shell.command_counter",
6
8
  "shell.rsync_commands",
@@ -20,7 +22,19 @@ class KuberKit::Shell::LocalShell < KuberKit::Shell::AbstractShell
20
22
  end
21
23
 
22
24
  if result && result != "" && log_command
23
- ui.print_debug("LocalShell", "Finished [#{command_number}] with result: \n ----\n#{result.grey}\n ----")
25
+ print_result = result
26
+ print_result_lines = print_result.split("\n")
27
+
28
+ if print_result_lines.count >= MAX_LINES_TO_PRINT
29
+ print_result = [
30
+ "[Result is too long, showing only first and last items]".yellow,
31
+ print_result_lines.first,
32
+ "[#{print_result_lines.count - 2} lines not showing]".yellow,
33
+ print_result_lines.last
34
+ ].join("\n")
35
+ end
36
+
37
+ ui.print_debug("LocalShell", "Finished [#{command_number}] with result: \n ----\n#{print_result.grey}\n ----")
24
38
  end
25
39
 
26
40
  if $?.exitstatus != 0
@@ -1,3 +1,3 @@
1
1
  module KuberKit
2
- VERSION = "0.4.9"
2
+ VERSION = "0.5.4"
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.9
4
+ version: 0.5.4
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-11 00:00:00.000000000 Z
11
+ date: 2021-03-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: contracts-lite
@@ -165,6 +165,7 @@ files:
165
165
  - ".ruby-gemset"
166
166
  - ".ruby-version"
167
167
  - ".travis.yml"
168
+ - CHANGELOG.md
168
169
  - Gemfile
169
170
  - Gemfile.lock
170
171
  - LICENSE.txt
@@ -209,7 +210,10 @@ files:
209
210
  - lib/kuber_kit/actions/kubectl_attacher.rb
210
211
  - lib/kuber_kit/actions/kubectl_console.rb
211
212
  - lib/kuber_kit/actions/kubectl_describe.rb
213
+ - lib/kuber_kit/actions/kubectl_env.rb
214
+ - lib/kuber_kit/actions/kubectl_get.rb
212
215
  - lib/kuber_kit/actions/kubectl_logs.rb
216
+ - lib/kuber_kit/actions/service_checker.rb
213
217
  - lib/kuber_kit/actions/service_deployer.rb
214
218
  - lib/kuber_kit/actions/service_reader.rb
215
219
  - lib/kuber_kit/actions/template_reader.rb
@@ -237,6 +241,7 @@ files:
237
241
  - lib/kuber_kit/core/context_helper/context_vars.rb
238
242
  - lib/kuber_kit/core/context_helper/image_helper.rb
239
243
  - lib/kuber_kit/core/context_helper/service_helper.rb
244
+ - lib/kuber_kit/core/dependencies/abstract_dependency_resolver.rb
240
245
  - lib/kuber_kit/core/env_files/abstract_env_file.rb
241
246
  - lib/kuber_kit/core/env_files/artifact_file.rb
242
247
  - lib/kuber_kit/core/env_files/env_file_store.rb
@@ -273,11 +278,13 @@ files:
273
278
  - lib/kuber_kit/image_compiler/image_builder.rb
274
279
  - lib/kuber_kit/image_compiler/image_dependency_resolver.rb
275
280
  - lib/kuber_kit/image_compiler/version_tag_builder.rb
281
+ - lib/kuber_kit/kubernetes/resource_selector.rb
276
282
  - lib/kuber_kit/kubernetes/resources_fetcher.rb
277
283
  - lib/kuber_kit/preprocessing/file_preprocessor.rb
278
284
  - lib/kuber_kit/preprocessing/text_preprocessor.rb
279
285
  - lib/kuber_kit/service_deployer/action_handler.rb
280
286
  - lib/kuber_kit/service_deployer/deployer.rb
287
+ - lib/kuber_kit/service_deployer/service_dependency_resolver.rb
281
288
  - lib/kuber_kit/service_deployer/service_list_resolver.rb
282
289
  - lib/kuber_kit/service_deployer/strategies/abstract.rb
283
290
  - lib/kuber_kit/service_deployer/strategies/docker.rb