krates 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (293) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +212 -0
  3. data/LOGO +10 -0
  4. data/VERSION +1 -0
  5. data/bin/krates +23 -0
  6. data/lib/kontena/autoload_core.rb +19 -0
  7. data/lib/kontena/callback.rb +60 -0
  8. data/lib/kontena/callbacks/.gitkeep +0 -0
  9. data/lib/kontena/callbacks/auth/01_list_and_select_grid_after_master_auth.rb +26 -0
  10. data/lib/kontena/callbacks/master/01_clear_current_master_after_terminate.rb +19 -0
  11. data/lib/kontena/callbacks/master/deploy/01_show_logo_before_deploy.rb +14 -0
  12. data/lib/kontena/callbacks/master/deploy/04_default_master_version.rb +18 -0
  13. data/lib/kontena/callbacks/master/deploy/05_before_deploy_configuration_wizard.rb +105 -0
  14. data/lib/kontena/callbacks/master/deploy/40_install_ssl_certificate_after_deploy.rb +32 -0
  15. data/lib/kontena/callbacks/master/deploy/50_authenticate_after_deploy.rb +66 -0
  16. data/lib/kontena/callbacks/master/deploy/55_create_initial_grid_after_deploy.rb +21 -0
  17. data/lib/kontena/callbacks/master/deploy/56_set_server_provider_after_deploy.rb +24 -0
  18. data/lib/kontena/callbacks/master/deploy/60_configure_auth_provider_after_deploy.rb +31 -0
  19. data/lib/kontena/callbacks/master/deploy/70_invite_self_after_deploy.rb +95 -0
  20. data/lib/kontena/callbacks/master/deploy/90_proptip_after_deploy.rb +33 -0
  21. data/lib/kontena/cli/browser_launcher.rb +61 -0
  22. data/lib/kontena/cli/bytes_helper.rb +40 -0
  23. data/lib/kontena/cli/certificate/authorize_command.rb +107 -0
  24. data/lib/kontena/cli/certificate/common.rb +16 -0
  25. data/lib/kontena/cli/certificate/domain_authorization/list_command.rb +24 -0
  26. data/lib/kontena/cli/certificate/domain_authorization/remove_authorization_command.rb +25 -0
  27. data/lib/kontena/cli/certificate/domain_authorize_command.rb +7 -0
  28. data/lib/kontena/cli/certificate/export_command.rb +28 -0
  29. data/lib/kontena/cli/certificate/get_command.rb +33 -0
  30. data/lib/kontena/cli/certificate/import_command.rb +61 -0
  31. data/lib/kontena/cli/certificate/list_command.rb +75 -0
  32. data/lib/kontena/cli/certificate/register_command.rb +30 -0
  33. data/lib/kontena/cli/certificate/remove_command.rb +23 -0
  34. data/lib/kontena/cli/certificate/request_command.rb +20 -0
  35. data/lib/kontena/cli/certificate/show_command.rb +22 -0
  36. data/lib/kontena/cli/certificate_command.rb +18 -0
  37. data/lib/kontena/cli/cloud/login_command.rb +186 -0
  38. data/lib/kontena/cli/cloud/logout_command.rb +14 -0
  39. data/lib/kontena/cli/cloud/master/add_command.rb +156 -0
  40. data/lib/kontena/cli/cloud/master/list_command.rb +35 -0
  41. data/lib/kontena/cli/cloud/master/remove_command.rb +68 -0
  42. data/lib/kontena/cli/cloud/master/show_command.rb +21 -0
  43. data/lib/kontena/cli/cloud/master/update_command.rb +52 -0
  44. data/lib/kontena/cli/cloud/master_command.rb +14 -0
  45. data/lib/kontena/cli/cloud_command.rb +13 -0
  46. data/lib/kontena/cli/common.rb +360 -0
  47. data/lib/kontena/cli/config.rb +662 -0
  48. data/lib/kontena/cli/container_command.rb +10 -0
  49. data/lib/kontena/cli/containers/exec_command.rb +31 -0
  50. data/lib/kontena/cli/containers/inspect_command.rb +16 -0
  51. data/lib/kontena/cli/containers/list_command.rb +51 -0
  52. data/lib/kontena/cli/containers/logs_command.rb +19 -0
  53. data/lib/kontena/cli/etcd/common.rb +8 -0
  54. data/lib/kontena/cli/etcd/get_command.rb +26 -0
  55. data/lib/kontena/cli/etcd/health_command.rb +53 -0
  56. data/lib/kontena/cli/etcd/list_command.rb +36 -0
  57. data/lib/kontena/cli/etcd/mkdir_command.rb +23 -0
  58. data/lib/kontena/cli/etcd/remove_command.rb +29 -0
  59. data/lib/kontena/cli/etcd/set_command.rb +24 -0
  60. data/lib/kontena/cli/etcd_command.rb +12 -0
  61. data/lib/kontena/cli/external_registries/add_command.rb +25 -0
  62. data/lib/kontena/cli/external_registries/list_command.rb +23 -0
  63. data/lib/kontena/cli/external_registries/remove_command.rb +17 -0
  64. data/lib/kontena/cli/external_registry_command.rb +9 -0
  65. data/lib/kontena/cli/grid_command.rb +21 -0
  66. data/lib/kontena/cli/grid_options.rb +12 -0
  67. data/lib/kontena/cli/grids/audit_log_command.rb +22 -0
  68. data/lib/kontena/cli/grids/cloud_config_command.rb +53 -0
  69. data/lib/kontena/cli/grids/common.rb +182 -0
  70. data/lib/kontena/cli/grids/create_command.rb +48 -0
  71. data/lib/kontena/cli/grids/current_command.rb +25 -0
  72. data/lib/kontena/cli/grids/env_command.rb +32 -0
  73. data/lib/kontena/cli/grids/events_command.rb +50 -0
  74. data/lib/kontena/cli/grids/health_command.rb +69 -0
  75. data/lib/kontena/cli/grids/list_command.rb +59 -0
  76. data/lib/kontena/cli/grids/logs_command.rb +35 -0
  77. data/lib/kontena/cli/grids/remove_command.rb +31 -0
  78. data/lib/kontena/cli/grids/show_command.rb +25 -0
  79. data/lib/kontena/cli/grids/trusted_subnet_command.rb +10 -0
  80. data/lib/kontena/cli/grids/trusted_subnets/add_command.rb +18 -0
  81. data/lib/kontena/cli/grids/trusted_subnets/list_command.rb +18 -0
  82. data/lib/kontena/cli/grids/trusted_subnets/remove_command.rb +26 -0
  83. data/lib/kontena/cli/grids/update_command.rb +35 -0
  84. data/lib/kontena/cli/grids/use_command.rb +26 -0
  85. data/lib/kontena/cli/grids/user_command.rb +9 -0
  86. data/lib/kontena/cli/grids/users/add_command.rb +18 -0
  87. data/lib/kontena/cli/grids/users/list_command.rb +20 -0
  88. data/lib/kontena/cli/grids/users/remove_command.rb +20 -0
  89. data/lib/kontena/cli/helpers/exec_helper.rb +209 -0
  90. data/lib/kontena/cli/helpers/health_helper.rb +65 -0
  91. data/lib/kontena/cli/helpers/log_helper.rb +113 -0
  92. data/lib/kontena/cli/helpers/time_helper.rb +29 -0
  93. data/lib/kontena/cli/localhost_web_server.rb +113 -0
  94. data/lib/kontena/cli/log_formatters/compact.rb +65 -0
  95. data/lib/kontena/cli/log_formatters/strip_color.rb +13 -0
  96. data/lib/kontena/cli/logout_command.rb +10 -0
  97. data/lib/kontena/cli/master/audit_log_command.rb +19 -0
  98. data/lib/kontena/cli/master/config/export_command.rb +46 -0
  99. data/lib/kontena/cli/master/config/get_command.rb +26 -0
  100. data/lib/kontena/cli/master/config/import_command.rb +67 -0
  101. data/lib/kontena/cli/master/config/set_command.rb +19 -0
  102. data/lib/kontena/cli/master/config/unset_command.rb +20 -0
  103. data/lib/kontena/cli/master/config_command.rb +17 -0
  104. data/lib/kontena/cli/master/create_command.rb +74 -0
  105. data/lib/kontena/cli/master/current_command.rb +25 -0
  106. data/lib/kontena/cli/master/init_cloud_command.rb +45 -0
  107. data/lib/kontena/cli/master/join_command.rb +22 -0
  108. data/lib/kontena/cli/master/list_command.rb +24 -0
  109. data/lib/kontena/cli/master/login_command.rb +331 -0
  110. data/lib/kontena/cli/master/logout_command.rb +25 -0
  111. data/lib/kontena/cli/master/remove_command.rb +55 -0
  112. data/lib/kontena/cli/master/ssh_command.rb +72 -0
  113. data/lib/kontena/cli/master/token/common.rb +29 -0
  114. data/lib/kontena/cli/master/token/create_command.rb +50 -0
  115. data/lib/kontena/cli/master/token/current_command.rb +45 -0
  116. data/lib/kontena/cli/master/token/list_command.rb +39 -0
  117. data/lib/kontena/cli/master/token/remove_command.rb +19 -0
  118. data/lib/kontena/cli/master/token/show_command.rb +34 -0
  119. data/lib/kontena/cli/master/token_command.rb +13 -0
  120. data/lib/kontena/cli/master/use_command.rb +31 -0
  121. data/lib/kontena/cli/master/user/invite_command.rb +51 -0
  122. data/lib/kontena/cli/master/user/list_command.rb +29 -0
  123. data/lib/kontena/cli/master/user/remove_command.rb +24 -0
  124. data/lib/kontena/cli/master/user/role/add_command.rb +29 -0
  125. data/lib/kontena/cli/master/user/role/remove_command.rb +27 -0
  126. data/lib/kontena/cli/master/user/role_command.rb +6 -0
  127. data/lib/kontena/cli/master/user_command.rb +9 -0
  128. data/lib/kontena/cli/master_command.rb +21 -0
  129. data/lib/kontena/cli/node_command.rb +17 -0
  130. data/lib/kontena/cli/nodes/create_command.rb +25 -0
  131. data/lib/kontena/cli/nodes/env_command.rb +37 -0
  132. data/lib/kontena/cli/nodes/health_command.rb +47 -0
  133. data/lib/kontena/cli/nodes/label_command.rb +10 -0
  134. data/lib/kontena/cli/nodes/labels/add_command.rb +18 -0
  135. data/lib/kontena/cli/nodes/labels/list_command.rb +19 -0
  136. data/lib/kontena/cli/nodes/labels/remove_command.rb +32 -0
  137. data/lib/kontena/cli/nodes/list_command.rb +97 -0
  138. data/lib/kontena/cli/nodes/remove_command.rb +34 -0
  139. data/lib/kontena/cli/nodes/reset_token_command.rb +34 -0
  140. data/lib/kontena/cli/nodes/show_command.rb +56 -0
  141. data/lib/kontena/cli/nodes/ssh_command.rb +63 -0
  142. data/lib/kontena/cli/nodes/update_command.rb +31 -0
  143. data/lib/kontena/cli/plugin_command.rb +12 -0
  144. data/lib/kontena/cli/plugins/common.rb +8 -0
  145. data/lib/kontena/cli/plugins/install_command.rb +42 -0
  146. data/lib/kontena/cli/plugins/list_command.rb +31 -0
  147. data/lib/kontena/cli/plugins/search_command.rb +25 -0
  148. data/lib/kontena/cli/plugins/show_command.rb +17 -0
  149. data/lib/kontena/cli/plugins/uninstall_command.rb +31 -0
  150. data/lib/kontena/cli/plugins/upgrade_command.rb +60 -0
  151. data/lib/kontena/cli/registry/create_command.rb +151 -0
  152. data/lib/kontena/cli/registry/remove_command.rb +21 -0
  153. data/lib/kontena/cli/registry_command.rb +8 -0
  154. data/lib/kontena/cli/service_command.rb +28 -0
  155. data/lib/kontena/cli/services/container_command.rb +8 -0
  156. data/lib/kontena/cli/services/containers_command.rb +39 -0
  157. data/lib/kontena/cli/services/create_command.rb +105 -0
  158. data/lib/kontena/cli/services/deploy_command.rb +25 -0
  159. data/lib/kontena/cli/services/env_command.rb +9 -0
  160. data/lib/kontena/cli/services/envs/add_command.rb +21 -0
  161. data/lib/kontena/cli/services/envs/list_command.rb +22 -0
  162. data/lib/kontena/cli/services/envs/remove_command.rb +22 -0
  163. data/lib/kontena/cli/services/events_command.rb +36 -0
  164. data/lib/kontena/cli/services/exec_command.rb +107 -0
  165. data/lib/kontena/cli/services/link_command.rb +35 -0
  166. data/lib/kontena/cli/services/list_command.rb +66 -0
  167. data/lib/kontena/cli/services/logs_command.rb +33 -0
  168. data/lib/kontena/cli/services/monitor_command.rb +58 -0
  169. data/lib/kontena/cli/services/remove_command.rb +60 -0
  170. data/lib/kontena/cli/services/restart_command.rb +19 -0
  171. data/lib/kontena/cli/services/scale_command.rb +21 -0
  172. data/lib/kontena/cli/services/secret_command.rb +8 -0
  173. data/lib/kontena/cli/services/secrets/link_command.rb +26 -0
  174. data/lib/kontena/cli/services/secrets/unlink_command.rb +28 -0
  175. data/lib/kontena/cli/services/services_helper.rb +579 -0
  176. data/lib/kontena/cli/services/show_command.rb +26 -0
  177. data/lib/kontena/cli/services/start_command.rb +21 -0
  178. data/lib/kontena/cli/services/stats_command.rb +87 -0
  179. data/lib/kontena/cli/services/stop_command.rb +21 -0
  180. data/lib/kontena/cli/services/unlink_command.rb +30 -0
  181. data/lib/kontena/cli/services/update_command.rb +94 -0
  182. data/lib/kontena/cli/spinner.rb +205 -0
  183. data/lib/kontena/cli/stack_command.rb +21 -0
  184. data/lib/kontena/cli/stacks/build_command.rb +125 -0
  185. data/lib/kontena/cli/stacks/common.rb +209 -0
  186. data/lib/kontena/cli/stacks/deploy_command.rb +37 -0
  187. data/lib/kontena/cli/stacks/events_command.rb +33 -0
  188. data/lib/kontena/cli/stacks/inspect_command.rb +17 -0
  189. data/lib/kontena/cli/stacks/install_command.rb +95 -0
  190. data/lib/kontena/cli/stacks/label_command.rb +10 -0
  191. data/lib/kontena/cli/stacks/labels/add_command.rb +21 -0
  192. data/lib/kontena/cli/stacks/labels/common.rb +19 -0
  193. data/lib/kontena/cli/stacks/labels/list_command.rb +21 -0
  194. data/lib/kontena/cli/stacks/labels/remove_command.rb +21 -0
  195. data/lib/kontena/cli/stacks/list_command.rb +154 -0
  196. data/lib/kontena/cli/stacks/logs_command.rb +35 -0
  197. data/lib/kontena/cli/stacks/monitor_command.rb +93 -0
  198. data/lib/kontena/cli/stacks/registry/create_command.rb +24 -0
  199. data/lib/kontena/cli/stacks/registry/make_private_command.rb +24 -0
  200. data/lib/kontena/cli/stacks/registry/make_public_command.rb +24 -0
  201. data/lib/kontena/cli/stacks/registry/pull_command.rb +28 -0
  202. data/lib/kontena/cli/stacks/registry/push_command.rb +40 -0
  203. data/lib/kontena/cli/stacks/registry/remove_command.rb +30 -0
  204. data/lib/kontena/cli/stacks/registry/search_command.rb +42 -0
  205. data/lib/kontena/cli/stacks/registry/show_command.rb +65 -0
  206. data/lib/kontena/cli/stacks/registry_command.rb +12 -0
  207. data/lib/kontena/cli/stacks/remove_command.rb +80 -0
  208. data/lib/kontena/cli/stacks/restart_command.rb +24 -0
  209. data/lib/kontena/cli/stacks/service_generator.rb +131 -0
  210. data/lib/kontena/cli/stacks/service_generator_v2.rb +27 -0
  211. data/lib/kontena/cli/stacks/show_command.rb +168 -0
  212. data/lib/kontena/cli/stacks/stack_name.rb +71 -0
  213. data/lib/kontena/cli/stacks/stacks_helper.rb +83 -0
  214. data/lib/kontena/cli/stacks/stop_command.rb +24 -0
  215. data/lib/kontena/cli/stacks/upgrade_command.rb +264 -0
  216. data/lib/kontena/cli/stacks/validate_command.rb +75 -0
  217. data/lib/kontena/cli/stacks/yaml/custom_validators/affinities_validator.rb +19 -0
  218. data/lib/kontena/cli/stacks/yaml/custom_validators/build_validator.rb +22 -0
  219. data/lib/kontena/cli/stacks/yaml/custom_validators/certificates_validator.rb +22 -0
  220. data/lib/kontena/cli/stacks/yaml/custom_validators/extends_validator.rb +22 -0
  221. data/lib/kontena/cli/stacks/yaml/custom_validators/hooks_validator.rb +102 -0
  222. data/lib/kontena/cli/stacks/yaml/custom_validators/secrets_validator.rb +22 -0
  223. data/lib/kontena/cli/stacks/yaml/opto/certificates_resolver.rb +37 -0
  224. data/lib/kontena/cli/stacks/yaml/opto/prompt_resolver.rb +78 -0
  225. data/lib/kontena/cli/stacks/yaml/opto/service_instances_resolver.rb +25 -0
  226. data/lib/kontena/cli/stacks/yaml/opto/service_link_resolver.rb +80 -0
  227. data/lib/kontena/cli/stacks/yaml/opto/vault_cert_prompt_resolver.rb +39 -0
  228. data/lib/kontena/cli/stacks/yaml/opto/vault_resolver.rb +13 -0
  229. data/lib/kontena/cli/stacks/yaml/opto/vault_setter.rb +12 -0
  230. data/lib/kontena/cli/stacks/yaml/opto.rb +16 -0
  231. data/lib/kontena/cli/stacks/yaml/reader.rb +525 -0
  232. data/lib/kontena/cli/stacks/yaml/service_extender.rb +65 -0
  233. data/lib/kontena/cli/stacks/yaml/stack_file_loader/file_loader.rb +41 -0
  234. data/lib/kontena/cli/stacks/yaml/stack_file_loader/registry_loader.rb +24 -0
  235. data/lib/kontena/cli/stacks/yaml/stack_file_loader/uri_loader.rb +23 -0
  236. data/lib/kontena/cli/stacks/yaml/stack_file_loader.rb +152 -0
  237. data/lib/kontena/cli/stacks/yaml/validations.rb +119 -0
  238. data/lib/kontena/cli/stacks/yaml/validator_v3.rb +164 -0
  239. data/lib/kontena/cli/subcommand_loader.rb +83 -0
  240. data/lib/kontena/cli/table_generator.rb +128 -0
  241. data/lib/kontena/cli/vault/export_command.rb +24 -0
  242. data/lib/kontena/cli/vault/import_command.rb +75 -0
  243. data/lib/kontena/cli/vault/list_command.rb +37 -0
  244. data/lib/kontena/cli/vault/read_command.rb +27 -0
  245. data/lib/kontena/cli/vault/remove_command.rb +23 -0
  246. data/lib/kontena/cli/vault/update_command.rb +24 -0
  247. data/lib/kontena/cli/vault/write_command.rb +23 -0
  248. data/lib/kontena/cli/vault_command.rb +13 -0
  249. data/lib/kontena/cli/version.rb +10 -0
  250. data/lib/kontena/cli/version_command.rb +20 -0
  251. data/lib/kontena/cli/volume_command.rb +9 -0
  252. data/lib/kontena/cli/volumes/create_command.rb +42 -0
  253. data/lib/kontena/cli/volumes/list_command.rb +29 -0
  254. data/lib/kontena/cli/volumes/remove_command.rb +29 -0
  255. data/lib/kontena/cli/volumes/show_command.rb +38 -0
  256. data/lib/kontena/cli/vpn/config_command.rb +27 -0
  257. data/lib/kontena/cli/vpn/create_command.rb +99 -0
  258. data/lib/kontena/cli/vpn/remove_command.rb +22 -0
  259. data/lib/kontena/cli/vpn_command.rb +9 -0
  260. data/lib/kontena/cli/whoami_command.rb +38 -0
  261. data/lib/kontena/client.rb +574 -0
  262. data/lib/kontena/command.rb +251 -0
  263. data/lib/kontena/debug_instrumentor.rb +80 -0
  264. data/lib/kontena/errors.rb +50 -0
  265. data/lib/kontena/light_prompt.rb +103 -0
  266. data/lib/kontena/machine/cert_helper.rb +43 -0
  267. data/lib/kontena/machine/cloud_config/cloudinit.yml +82 -0
  268. data/lib/kontena/machine/cloud_config/node_generator.rb +28 -0
  269. data/lib/kontena/machine/common.rb +17 -0
  270. data/lib/kontena/machine/random_name.rb +42 -0
  271. data/lib/kontena/main_command.rb +66 -0
  272. data/lib/kontena/plugin_manager/cleaner.rb +33 -0
  273. data/lib/kontena/plugin_manager/common.rb +89 -0
  274. data/lib/kontena/plugin_manager/installer.rb +78 -0
  275. data/lib/kontena/plugin_manager/loader.rb +93 -0
  276. data/lib/kontena/plugin_manager/rubygems_client.rb +59 -0
  277. data/lib/kontena/plugin_manager/uninstaller.rb +34 -0
  278. data/lib/kontena/plugin_manager.rb +26 -0
  279. data/lib/kontena/presets/github_auth_provider.yml +11 -0
  280. data/lib/kontena/presets/kontena_auth_provider.yml +11 -0
  281. data/lib/kontena/scripts/completer +9 -0
  282. data/lib/kontena/scripts/completer.rb +334 -0
  283. data/lib/kontena/scripts/init +18 -0
  284. data/lib/kontena/scripts/kontena.zsh +11 -0
  285. data/lib/kontena/scripts/krates.bash +8 -0
  286. data/lib/kontena/stacks/change_resolver.rb +118 -0
  287. data/lib/kontena/stacks/stack_data.rb +58 -0
  288. data/lib/kontena/stacks/stack_data_set.rb +51 -0
  289. data/lib/kontena/stacks_cache.rb +110 -0
  290. data/lib/kontena/stacks_client.rb +177 -0
  291. data/lib/kontena/util.rb +116 -0
  292. data/lib/kontena_cli.rb +190 -0
  293. metadata +518 -0
@@ -0,0 +1,168 @@
1
+ require_relative 'common'
2
+ require 'yaml'
3
+
4
+ module Kontena::Cli::Stacks
5
+ class ShowCommand < Kontena::Command
6
+ include Kontena::Cli::Common
7
+ include Kontena::Cli::GridOptions
8
+ include Common
9
+
10
+ banner "Show information and status of a stack in a grid on Kontena Master"
11
+
12
+ parameter "NAME", "Stack name"
13
+
14
+ requires_current_master
15
+ requires_current_master_token
16
+
17
+ option '--values', :flag, 'Output the variable-value pairs as YAML'
18
+ include Common::StackValuesToOption
19
+
20
+ def execute
21
+ write_variables if values_to
22
+ values? ? show_variables : show_stack
23
+ end
24
+
25
+ def variables
26
+ @variables ||= stack['variables'] || {}
27
+ end
28
+
29
+ def metadata
30
+ @metadata ||= stack['metadata'] || {}
31
+ end
32
+
33
+ def stack
34
+ @stack ||= client.get("stacks/#{current_grid}/#{name}")
35
+ end
36
+
37
+ def show_variables
38
+ puts variable_yaml
39
+ end
40
+
41
+ def variable_yaml
42
+ ::YAML.dump(variables)
43
+ end
44
+
45
+ def write_variables
46
+ File.write(values_to, variable_yaml)
47
+ end
48
+
49
+ def show_stack
50
+ puts "#{stack['name']}:"
51
+ puts " created: #{stack['created_at']}"
52
+ puts " updated: #{stack['updated_at']}"
53
+ puts " state: #{stack['state']}"
54
+ puts " stack: #{stack['stack']}"
55
+ puts " version: #{stack['version']}"
56
+ puts " revision: #{stack['revision']}"
57
+ puts " expose: #{stack['expose'] || '-'}"
58
+
59
+ puts " variables:#{' -' if variables.empty?}"
60
+ variables.each do |var, val|
61
+ puts " #{var}: #{val}"
62
+ end
63
+
64
+ puts " metadata:#{' -' if metadata.empty?}"
65
+ unless metadata.empty?
66
+ output_lines = ::YAML.dump(metadata).split(/[\r\n]/)
67
+ output_lines.shift # get rid of "---"
68
+ puts output_lines.map { |line| ' %s' % line }.join("\n")
69
+ end
70
+
71
+ puts " parent: #{stack['parent'] ? stack['parent']['name'] : '-'}"
72
+ if stack['children'] && !stack['children'].empty?
73
+ puts " children:"
74
+ stack['children'].each do |child|
75
+ puts " - #{child['name']}"
76
+ end
77
+ end
78
+
79
+ puts " services:"
80
+ stack['services'].each do |service|
81
+ show_service(service['id'])
82
+ end
83
+ end
84
+
85
+ # @param [String] service_id
86
+ def show_service(service_id)
87
+ token = require_token
88
+ service = get_service(token, service_id)
89
+ pad = ' '.freeze
90
+ puts "#{pad}#{service['name']}:"
91
+ puts "#{pad} created: #{service['created_at']}"
92
+ puts "#{pad} updated: #{service['updated_at']}"
93
+ puts "#{pad} image: #{service['image']}"
94
+ puts "#{pad} revision: #{service['stack_revision']}"
95
+ puts "#{pad} state: #{service['state'] }"
96
+ if service['health_status']
97
+ puts "#{pad} health_status:"
98
+ puts "#{pad} healthy: #{service['health_status']['healthy']}"
99
+ puts "#{pad} total: #{service['health_status']['total']}"
100
+ end
101
+ puts "#{pad} stateful: #{service['stateful'] == true ? 'yes' : 'no' }"
102
+ puts "#{pad} scaling: #{service['instances'] }"
103
+ puts "#{pad} strategy: #{service['strategy']}"
104
+ puts "#{pad} read_only: #{service['read_only'] == true ? 'yes' : 'no'}"
105
+ puts "#{pad} deploy_opts:"
106
+ puts "#{pad} min_health: #{service['deploy_opts']['min_health']}"
107
+ if service['deploy_opts']['wait_for_port']
108
+ puts "#{pad} wait_for_port: #{service['deploy_opts']['wait_for_port']}"
109
+ end
110
+ if service['deploy_opts']['interval']
111
+ puts "#{pad} interval: #{service['deploy_opts']['interval']}"
112
+ end
113
+ puts "#{pad} dns: #{service['dns']}"
114
+
115
+ if service['affinity'].to_a.size > 0
116
+ puts "#{pad} affinity: "
117
+ service['affinity'].to_a.each do |a|
118
+ puts "#{pad} - #{a}"
119
+ end
120
+ end
121
+
122
+ if service['secrets'].to_a.size > 0
123
+ puts "#{pad} secrets: "
124
+ service['secrets'].to_a.each do |s|
125
+ puts "#{pad} - secret: #{s['secret']}"
126
+ puts "#{pad} name: #{s['name']}"
127
+ puts "#{pad} type: #{s['type']}"
128
+ end
129
+ end
130
+
131
+ unless service['cmd'].to_s.empty?
132
+ if service['cmd']
133
+ puts "#{pad} cmd: #{service['cmd'].join(' ')}"
134
+ else
135
+ puts "#{pad} cmd: "
136
+ end
137
+ end
138
+
139
+ if service['ports'].to_a.size > 0
140
+ puts "#{pad} ports:"
141
+ service['ports'].to_a.each do |p|
142
+ puts "#{pad} - #{p['node_port']}:#{p['container_port']}/#{p['protocol']}"
143
+ end
144
+ end
145
+
146
+ if service['volumes'].to_a.size > 0
147
+ puts "#{pad} volumes:"
148
+ service['volumes'].to_a.each do |v|
149
+ puts "#{pad} - #{v}"
150
+ end
151
+ end
152
+
153
+ if service['volumes_from'].to_a.size > 0
154
+ puts "#{pad} volumes_from:"
155
+ service['volumes_from'].to_a.each do |v|
156
+ puts "#{pad} - #{v}"
157
+ end
158
+ end
159
+
160
+ if service['links'].to_a.size > 0
161
+ puts "#{pad} links: "
162
+ service['links'].to_a.each do |l|
163
+ puts "#{pad} - #{l['alias']} => #{l['id']}"
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,71 @@
1
+ require 'semantic'
2
+
3
+ module Kontena::Cli::Stacks
4
+ class StackName
5
+ # A class for parsing stack name strings, such as kontena/foo:1.0.0
6
+
7
+ attr_reader :user, :stack, :version
8
+
9
+ # @param definition [String] such as kontena/foo:1.0.0
10
+ # @param version [String] set version separately
11
+ # @return [StackName]
12
+ # @example
13
+ # name = StackName.new('kontena/foo:0.1.0')
14
+ # name.user => 'kontena'
15
+ # name.stack => 'foo'
16
+ # name.version => '0.1.0'
17
+ # name.stack_name => 'kontena/foo'
18
+ # name.to_s => 'kontena/foo:0.1.0
19
+ def initialize(definition = nil, version = nil)
20
+ if definition.kind_of?(Hash)
21
+ @user = definition[:user] || definition['user']
22
+ @stack = definition[:stack] || definition['stack']
23
+ @version = definition[:version] || definition['version'] || version
24
+ elsif definition.kind_of?(String)
25
+ parsed = parse(definition)
26
+ @user = parsed[:user]
27
+ @stack = parsed[:stack]
28
+ @version = parsed[:version] || version
29
+ end
30
+ end
31
+
32
+ # Stack name without version
33
+ # @return [String] example: kontena/foo
34
+ def stack_name
35
+ [user, stack].compact.join('/')
36
+ end
37
+
38
+ # Full stack name including version if present
39
+ # @return [String] example: kontena/foo:0.1.0
40
+ def to_s
41
+ version ? "#{stack_name}:#{version}" : stack_name
42
+ end
43
+ alias to_str to_s
44
+
45
+ # True when version is a prerelease
46
+ # @return [NilClass,TrueClass,FalseClass] nil when no version, true when prerelease, false when not.
47
+ def pre?
48
+ return nil if version.nil?
49
+ !Semantic::Version.new(version).pre.nil?
50
+ end
51
+
52
+ private
53
+
54
+ def parse(definition)
55
+ return {} if definition.empty?
56
+ name, version = definition.split(':', 2)
57
+ if name.include?('/')
58
+ user, stack = name.split('/', 2)
59
+ else
60
+ user = nil
61
+ stack = name
62
+ end
63
+ {
64
+ user: user,
65
+ stack: stack,
66
+ version: version
67
+ }
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,83 @@
1
+ module Kontena::Cli::Stacks
2
+ module StacksHelper
3
+
4
+ def wait_for_deployment_to_start(deployment, timeout = 600)
5
+ started = false
6
+ Timeout::timeout(timeout) do
7
+ while deployment['state'] == 'created'
8
+ sleep 1
9
+ deployment = client.get("stacks/#{deployment['stack_id']}/deploys/#{deployment['id']}")
10
+ end
11
+ if deployment['state'] == 'error'
12
+ puts "Stack deploy failed"
13
+ deployment['service_deploys'].each do |service_deploy|
14
+ if service_deploy['state'] == 'error'
15
+ puts " - #{service_deploy['reason']}"
16
+ end
17
+ end
18
+
19
+ abort
20
+ end
21
+ end
22
+
23
+ started
24
+ rescue Timeout::Error
25
+ raise 'deploy timed out'
26
+ end
27
+
28
+ # @param [Hash] deployment
29
+ # @return [Boolean]
30
+ def wait_for_deploy_to_finish(deployment, timeout = 600)
31
+ deployed = false
32
+ states = %w(success error)
33
+ tracked_services = []
34
+ Timeout::timeout(timeout) do
35
+ until deployed
36
+ deployment = client.get("stacks/#{deployment['stack_id']}/deploys/#{deployment['id']}")
37
+ service_deploy = deployment['service_deploys'].find{ |s| s['state'] == 'ongoing' }
38
+ if service_deploy
39
+ tracked_services << service_deploy['id']
40
+ wait_for_service_deploy(service_deploy)
41
+ end
42
+ if states.include?(deployment['state'])
43
+ deployed = true
44
+ deployment['service_deploys'].select{ |s| !tracked_services.include?(s['id']) }.each do |s|
45
+ wait_for_service_deploy(s)
46
+ end
47
+ else
48
+ sleep 1
49
+ end
50
+ end
51
+ if deployment['state'] == 'error'
52
+ deployment['service_deploys'].each do |service_deploy|
53
+ if service_deploy['state'] == 'error'
54
+ $stderr.puts "Deployment of service #{pastel.cyan(service_deploy['service_id'])} failed:"
55
+ $stderr.puts " - #{service_deploy['reason'].strip}"
56
+ service_deploy['instance_deploys'].each do |instance_deploy|
57
+ if instance_deploy['state'] == 'error'
58
+ $stderr.puts " - " + "#{instance_deploy['error'].strip} (on node #{pastel.cyan(instance_deploy['node'])})"
59
+ end
60
+ end
61
+ end
62
+ end
63
+ abort
64
+ end
65
+ end
66
+
67
+ deployed
68
+ rescue Timeout::Error
69
+ raise 'deploy timed out'
70
+ end
71
+
72
+ def wait_for_service_deploy(service_deploy)
73
+ name = service_deploy['service_id'].split('/')[-1]
74
+ spinner "Deploying service #{pastel.cyan(name)}" do |spin|
75
+ until service_deploy['finished_at']
76
+ sleep 1
77
+ service_deploy = client.get("services/#{service_deploy['service_id']}/deploys/#{service_deploy['id']}")
78
+ end
79
+ spin.fail if service_deploy['state'] == 'error'
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,24 @@
1
+ require_relative 'common'
2
+
3
+ module Kontena::Cli::Stacks
4
+ class StopCommand < Kontena::Command
5
+ include Kontena::Cli::Common
6
+ include Kontena::Cli::GridOptions
7
+ include Common
8
+
9
+ banner "Stops all services of a stack"
10
+
11
+ parameter "NAME ...", "Stack name", attribute_name: :names
12
+
13
+ requires_current_master
14
+ requires_current_master_token
15
+
16
+ def execute
17
+ names.each do |name|
18
+ spinner "Sending stop signal for stack #{name} services" do
19
+ client.post("stacks/#{current_grid}/#{name}/stop", {})
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,264 @@
1
+ require 'json'
2
+ require 'kontena/stacks/change_resolver'
3
+ require_relative 'common'
4
+
5
+ module Kontena::Cli::Stacks
6
+ class UpgradeCommand < Kontena::Command
7
+ include Kontena::Cli::Common
8
+ include Kontena::Cli::GridOptions
9
+ include Common
10
+
11
+ banner "Upgrades a stack in a grid on Kontena Master"
12
+
13
+ parameter "NAME", "Stack name"
14
+
15
+ include Common::StackFileOrNameParam
16
+
17
+ include Common::StackValuesToOption
18
+ include Common::StackValuesFromOption
19
+
20
+ option '--[no-]deploy', :flag, 'Trigger deploy after upgrade', default: true
21
+
22
+ option '--force', :flag, 'Force upgrade'
23
+ option '--skip-dependencies', :flag, "Do not upgrade any stack dependencies", default: false
24
+ option '--reuse-values', :flag, "Reuse existing values"
25
+ option '--dry-run', :flag, "Simulate upgrade"
26
+
27
+ requires_current_master
28
+ requires_current_master_token
29
+
30
+ # @return [Kontena::Stacks::ChangeResolver]
31
+ def execute
32
+ old_data = spinner "Reading stack #{pastel.cyan(stack_name)} from master" do
33
+ gather_master_data(stack_name)
34
+ end
35
+
36
+ kontena_requirement = loader.yaml.dig('meta', 'required_kontena_version')
37
+ unless kontena_requirement.nil?
38
+ master_version = Gem::Version.new(client.server_version)
39
+ unless Gem::Requirement.new(kontena_requirement).satisfied_by?(master_version)
40
+ puts "#{pastel.red("Warning: ")} Stack requires kontena version #{kontena_requirement} but Master version is #{master_version}"
41
+ confirm("Are you sure? You can skip this prompt by running this command with --force option") unless force?
42
+ end
43
+ end
44
+
45
+ new_data = spinner "Parsing #{pastel.cyan(source)}" do
46
+ loader.flat_dependencies(
47
+ stack_name,
48
+ variables: values_from_options
49
+ )
50
+ end
51
+
52
+ changes = process_data(old_data, new_data)
53
+
54
+ display_report(changes)
55
+
56
+ return if dry_run?
57
+
58
+ get_confirmation(changes)
59
+
60
+ deployable_stacks = []
61
+ deployable_stacks.concat run_installs(changes)
62
+ deployable_stacks.concat run_upgrades(changes)
63
+
64
+ run_deploys(deployable_stacks) if deploy?
65
+
66
+ run_removes(changes.removed_stacks)
67
+
68
+ changes
69
+ end
70
+
71
+ private
72
+
73
+ # Recursively fetch master data in StackFileLoader#flat_dependencies format
74
+ # @return [Hash{string => Hash}] stackname => hash
75
+ def gather_master_data(stackname)
76
+ response = fetch_master_data(stackname)
77
+ children = response.delete('children') || []
78
+ result = { stackname => { stack_data: response } }
79
+ children.each do |child|
80
+ result.merge!(gather_master_data(child['name']))
81
+ end
82
+ result
83
+ end
84
+
85
+ # Preprocess data and return a ChangeResolver
86
+ # @param old_data [Hash] data from master
87
+ # @param new_data [Hash] data from files
88
+ # @return [Kontena::Cli::Stacks::ChangeRsolver]
89
+ def process_data(old_data, new_data)
90
+ logger.debug { "Master stacks: #{old_data.keys.join(",")} YAML stacks: #{new_data.keys.join(",")}" }
91
+
92
+ new_data.reverse_each do |stackname, data|
93
+ spinner "Processing stack #{pastel.cyan(stackname)}"
94
+ process_stack_data(stackname, data, old_data)
95
+ hint_on_validation_notifications(reader.notifications, reader.loader.source)
96
+ abort_on_validation_errors(reader.errors, reader.loader.source)
97
+ end
98
+
99
+ old_set = Kontena::Stacks::StackDataSet.new(old_data)
100
+ new_set = Kontena::Stacks::StackDataSet.new(new_data)
101
+ if skip_dependencies?
102
+ [old_set, new_set].each(&:remove_dependencies)
103
+ end
104
+ spinner "Analyzing upgrade" do
105
+ Kontena::Stacks::ChangeResolver.new(old_set, new_set)
106
+ end
107
+ end
108
+
109
+ # @param stackname [String]
110
+ # @param data [Hash]
111
+ # @param old_data [Hash]
112
+ def process_stack_data(stackname, data, old_data)
113
+ prev_env = ENV.clone
114
+ reader = data[:loader].reader
115
+ values = data[:variables]
116
+ if reuse_values? && old_data[stackname]
117
+ old_vars = old_data[stackname][:stack_data]['variables']
118
+ values = old_vars.merge(values)
119
+ end
120
+ set_env_variables(stackname, current_grid) # set envs for execution time
121
+ parsed_stack = reader.execute(
122
+ values: values,
123
+ defaults: old_data[stackname].nil? ? nil : old_data[stackname][:stack_data]['variables'],
124
+ parent_name: data[:parent_name],
125
+ name: data[:name]
126
+ )
127
+ data[:stack_data] = parsed_stack
128
+ ensure
129
+ prev_env.each { |k, v| ENV[k] = v }
130
+ end
131
+
132
+ # @param changes [Kontena::Stacks::ChangeResolver]
133
+ def display_report(changes)
134
+ puts
135
+ caret "Calculated changes:", dots: false
136
+
137
+ unless changes.removed_stacks.empty?
138
+ changes.removed_stacks.each { |stack|
139
+ puts " #{pastel.red('-')} #{stack}"
140
+ changes.removed_services.select { |s| s.split('/')[0] == stack }.each do |s|
141
+ puts " #{pastel.red('-')} #{s}"
142
+ end
143
+ }
144
+ end
145
+
146
+ unless changes.replaced_stacks.empty?
147
+ changes.replaced_stacks.each { |stack|
148
+ puts " #{pastel.yellow('-/+')} #{stack}"
149
+ changes.upgraded_services.select { |s| s.split('/')[0] == stack }.each do |s|
150
+ puts " #{pastel.cyan('~')} #{s}"
151
+ end
152
+ changes.added_services.select { |s| s.split('/')[0] == stack }.each do |s|
153
+ puts " #{pastel.green('+')} #{s}"
154
+ end
155
+ changes.removed_services.select { |s| s.split('/')[0] == stack }.each do |s|
156
+ puts " #{pastel.red('-')} #{s}"
157
+ end
158
+ }
159
+ changes.replaced_stacks.each do |installed_name, data|
160
+ puts "- #{pastel.yellow(installed_name)} from #{pastel.cyan(data[:from])} to #{pastel.cyan(data[:to])}"
161
+ end
162
+ puts
163
+ end
164
+
165
+ unless changes.added_stacks.empty?
166
+ changes.added_stacks.each { |stack|
167
+ puts " #{pastel.green('+')} #{stack}"
168
+ changes.added_services.select { |s| s.split('/')[0] == stack }.each do |s|
169
+ puts " #{pastel.green('+')} #{s}"
170
+ end
171
+ }
172
+ end
173
+
174
+ unless changes.upgraded_stacks.empty?
175
+ changes.upgraded_stacks.each { |stack|
176
+ puts " #{pastel.cyan('~')} #{stack}"
177
+ changes.upgraded_services.select { |s| s.split('/')[0] == stack }.each do |s|
178
+ puts " #{pastel.cyan('~')} #{s}"
179
+ end
180
+ changes.added_services.select { |s| s.split('/')[0] == stack }.each do |s|
181
+ puts " #{pastel.green('+')} #{s}"
182
+ end
183
+ changes.removed_services.select { |s| s.split('/')[0] == stack }.each do |s|
184
+ puts " #{pastel.red('-')} #{s}"
185
+ end
186
+ }
187
+ end
188
+ puts
189
+ end
190
+
191
+ # requires heavier confirmation when something very dangerous is going to happen
192
+ def get_confirmation(changes)
193
+ unless force?
194
+ unless changes.safe?
195
+ puts "#{pastel.red('Warning:')} This can not be undone, data will be lost."
196
+ confirm
197
+ end
198
+ end
199
+ end
200
+
201
+ def deployable_stacks
202
+ @deployable_stacks ||= []
203
+ end
204
+
205
+ # @param removed_stacks [Array<String>]
206
+ def run_removes(removed_stacks)
207
+ removed_stacks.reverse_each do |removed_stack|
208
+ Kontena.run!('stack', 'remove', '--force', '--keep-dependencies', removed_stack)
209
+ end
210
+ end
211
+
212
+ # @param changes [Kontena::Stacks::ChangeResolver]
213
+ # @return [Array] an array of stack names that have been installed, but not yet deployed
214
+ def run_installs(changes)
215
+ deployable_stacks = []
216
+ changes.added_stacks.reverse_each do |added_stack|
217
+ data = changes.new_data[added_stack]
218
+ cmd = ['stack', 'install', '--name', added_stack, '--no-deploy']
219
+ cmd.concat ['--parent-name', data.parent] unless data.root?
220
+ data.variables.each do |k,v|
221
+ cmd.concat ['-v', "#{k}=#{v}"]
222
+ end
223
+ cmd << data.loader.source
224
+ caret "Installing new dependency #{cmd.last} as #{added_stack}"
225
+ deployable_stacks << added_stack
226
+ Kontena.run!(cmd)
227
+ end
228
+ deployable_stacks
229
+ end
230
+
231
+ # @param changes [Kontena::Stacks::ChangeResolver]
232
+ # @return [Array] an array of stack names that have been upgraded, but not yet deployed
233
+ def run_upgrades(changes)
234
+ deployable_stacks = []
235
+ changes.upgraded_stacks.reverse_each do |upgraded_stack|
236
+ data = changes.new_data[upgraded_stack]
237
+ spinner "Upgrading #{data.root? ? 'stack' : 'dependency'} #{pastel.cyan(upgraded_stack)}" do |spin|
238
+ deployable_stacks << upgraded_stack
239
+ update_stack(upgraded_stack, data.data) || spin.fail!
240
+ end
241
+ end
242
+ deployable_stacks
243
+ end
244
+
245
+ # @param deployable_stacks [Array<String>] an array of stack names that should be deployed
246
+ def run_deploys(deployable_stacks)
247
+ deployable_stacks.each do |deployable_stack|
248
+ Kontena.run!(['stack', 'deploy', deployable_stack])
249
+ end
250
+ end
251
+
252
+ def update_stack(name, data)
253
+ client.put(stack_url(name), data)
254
+ end
255
+
256
+ def stack_url(name)
257
+ "stacks/#{current_grid}/#{name}"
258
+ end
259
+
260
+ def fetch_master_data(stackname)
261
+ client.get(stack_url(stackname))
262
+ end
263
+ end
264
+ end
@@ -0,0 +1,75 @@
1
+ require_relative 'common'
2
+ require 'yaml'
3
+
4
+ module Kontena::Cli::Stacks
5
+ class ValidateCommand < Kontena::Command
6
+ include Kontena::Cli::Common
7
+ include Kontena::Cli::GridOptions
8
+ include Common
9
+
10
+ banner "Validates a YAML file"
11
+
12
+ include Common::StackFileOrNameParam
13
+ include Common::StackNameOption
14
+
15
+ include Common::StackValuesToOption
16
+ include Common::StackValuesFromOption
17
+
18
+ option '--online', :flag, "Enable connections to current master", default: false
19
+ option '--dependency-tree', :flag, "Show dependency tree"
20
+ option '--[no-]dependencies', :flag, "Validate dependencies", default: true
21
+ option '--parent-name', '[PARENT_NAME]', "Set parent name", hidden: true
22
+ option '--format', 'yaml|api-json', "Output Format", default: 'yaml'
23
+
24
+ def validate_dependencies
25
+ dependencies = loader.dependencies
26
+ return if dependencies.nil?
27
+ dependencies.each do |dependency|
28
+ target_name = "#{stack_name}-#{dependency['name']}"
29
+ cmd = ['stack', 'validate']
30
+ cmd << '--online' if online?
31
+ cmd.concat ['--parent-name', stack_name]
32
+
33
+ dependency['variables'].merge(dependency_values_from_options(dependency['name'])).each do |key, value|
34
+ cmd.concat ['-v', "#{key}=#{value}"]
35
+ end
36
+ cmd << dependency['stack']
37
+ Kontena.run(cmd)
38
+ end
39
+ end
40
+
41
+ def execute
42
+ if dependency_tree?
43
+ puts ::YAML.dump('name' => stack_name, 'stack' => source, 'depends' => stack['dependencies'])
44
+ exit 0
45
+ end
46
+
47
+ validate_dependencies if dependencies?
48
+
49
+ if online?
50
+ set_env_variables(stack_name, require_current_grid)
51
+ else
52
+ config.current_master = nil
53
+ set_env_variables(stack_name, 'validate', 'validate-platform')
54
+ end
55
+
56
+ stack # runs validations
57
+
58
+ hint_on_validation_notifications(reader.notifications, dependencies? ? loader.source : nil)
59
+ abort_on_validation_errors(reader.errors, dependencies? ? loader.source : nil)
60
+
61
+ dump_variables if values_to
62
+
63
+ case self.format
64
+ when 'api-json'
65
+ puts JSON.pretty_generate(stack)
66
+ when 'yaml'
67
+ result = ::YAML.dump(reader.fully_interpolated_yaml)
68
+ result = result.sub(/\A---$/, "---\n# #{loader.source}") if dependencies?
69
+ puts result
70
+ else
71
+ exit_with_error "Unknown --format=#{self.format}"
72
+ end
73
+ end
74
+ end
75
+ end